Completed
Push — AdamKasp--refactor-and-upgrade... ( dfa618...fc27b6 )
by Kamil
05:14
created

OrderRepository::countByCustomer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 1
nc 1
nop 1
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
    /**
318
     * {@inheritdoc}
319
     */
320
    public function findLatestInChannel(int $count, ChannelInterface $channel): array
321
    {
322
        return $this->createQueryBuilder('o')
323
            ->andWhere('o.channel = :channel')
324
            ->andWhere('o.state != :state')
325
            ->addOrderBy('o.checkoutCompletedAt', 'DESC')
326
            ->setParameter('channel', $channel)
327
            ->setParameter('state', OrderInterface::STATE_CART)
328
            ->setMaxResults($count)
329
            ->getQuery()
330
            ->getResult()
331
        ;
332
    }
333
334
    /**
335
     * {@inheritdoc}
336
     */
337
    public function findOrdersUnpaidSince(\DateTimeInterface $terminalDate): array
338
    {
339
        return $this->createQueryBuilder('o')
340
            ->where('o.checkoutState = :checkoutState')
341
            ->andWhere('o.paymentState != :paymentState')
342
            ->andWhere('o.state = :orderState')
343
            ->andWhere('o.checkoutCompletedAt < :terminalDate')
344
            ->setParameter('checkoutState', OrderCheckoutStates::STATE_COMPLETED)
345
            ->setParameter('paymentState', OrderPaymentStates::STATE_PAID)
346
            ->setParameter('orderState', OrderInterface::STATE_NEW)
347
            ->setParameter('terminalDate', $terminalDate)
348
            ->getQuery()
349
            ->getResult()
350
        ;
351
    }
352
353
    /**
354
     * {@inheritdoc}
355
     */
356
    public function findCartForSummary($id): ?OrderInterface
357
    {
358
        /** @var OrderInterface $order */
359
        $order = $this->createQueryBuilder('o')
360
            ->andWhere('o.id = :id')
361
            ->andWhere('o.state = :state')
362
            ->setParameter('id', $id)
363
            ->setParameter('state', OrderInterface::STATE_CART)
364
            ->getQuery()
365
            ->getOneOrNullResult()
366
        ;
367
368
        $this->associationHydrator->hydrateAssociations($order, [
369
            'adjustments',
370
            'items',
371
            'items.adjustments',
372
            'items.units',
373
            'items.units.adjustments',
374
            'items.variant',
375
            'items.variant.optionValues',
376
            'items.variant.optionValues.translations',
377
            'items.variant.product',
378
            'items.variant.product.translations',
379
            'items.variant.product.images',
380
            'items.variant.product.options',
381
            'items.variant.product.options.translations',
382
        ]);
383
384
        return $order;
385
    }
386
387
    /**
388
     * {@inheritdoc}
389
     */
390
    public function findCartForAddressing($id): ?OrderInterface
391
    {
392
        /** @var OrderInterface $order */
393
        $order = $this->createQueryBuilder('o')
394
            ->andWhere('o.id = :id')
395
            ->andWhere('o.state = :state')
396
            ->setParameter('id', $id)
397
            ->setParameter('state', OrderInterface::STATE_CART)
398
            ->getQuery()
399
            ->getOneOrNullResult()
400
        ;
401
402
        $this->associationHydrator->hydrateAssociations($order, [
403
            'items',
404
            'items.variant',
405
            'items.variant.product',
406
            'items.variant.product.translations',
407
        ]);
408
409
        return $order;
410
    }
411
412
    /**
413
     * {@inheritdoc}
414
     */
415
    public function findCartForSelectingShipping($id): ?OrderInterface
416
    {
417
        /** @var OrderInterface $order */
418
        $order = $this->createQueryBuilder('o')
419
            ->andWhere('o.id = :id')
420
            ->andWhere('o.state = :state')
421
            ->setParameter('id', $id)
422
            ->setParameter('state', OrderInterface::STATE_CART)
423
            ->getQuery()
424
            ->getOneOrNullResult()
425
        ;
426
427
        $this->associationHydrator->hydrateAssociations($order, [
428
            'items',
429
            'items.variant',
430
            'items.variant.product',
431
            'items.variant.product.translations',
432
        ]);
433
434
        return $order;
435
    }
436
437
    /**
438
     * {@inheritdoc}
439
     */
440
    public function findCartForSelectingPayment($id): ?OrderInterface
441
    {
442
        /** @var OrderInterface $order */
443
        $order = $this->createQueryBuilder('o')
444
            ->andWhere('o.id = :id')
445
            ->andWhere('o.state = :state')
446
            ->setParameter('id', $id)
447
            ->setParameter('state', OrderInterface::STATE_CART)
448
            ->getQuery()
449
            ->getOneOrNullResult()
450
        ;
451
452
        $this->associationHydrator->hydrateAssociations($order, [
453
            'items',
454
            'items.variant',
455
            'items.variant.product',
456
            'items.variant.product.translations',
457
        ]);
458
459
        return $order;
460
    }
461
}
462