Completed
Push — master ( 584969...3f5763 )
by
unknown
11:30
created

OrderRepository::getUniqueBuyersCount()   B

Complexity

Conditions 4
Paths 16

Size

Total Lines 23
Code Lines 16

Duplication

Lines 23
Ratio 100 %

Importance

Changes 2
Bugs 2 Features 0
Metric Value
c 2
b 2
f 0
dl 23
loc 23
rs 8.7972
cc 4
eloc 16
nc 16
nop 3
1
<?php
2
3
namespace OroCRM\Bundle\MagentoBundle\Entity\Repository;
4
5
use Doctrine\ORM\EntityManager;
6
use Doctrine\ORM\NoResultException;
7
use Doctrine\ORM\QueryBuilder;
8
9
use Oro\Bundle\DashboardBundle\Helper\DateHelper;
10
use Oro\Bundle\SecurityBundle\ORM\Walker\AclHelper;
11
use Oro\Bundle\EntityBundle\Exception\InvalidEntityException;
12
13
use OroCRM\Bundle\MagentoBundle\Entity\Cart;
14
use OroCRM\Bundle\MagentoBundle\Entity\Customer;
15
use OroCRM\Bundle\MagentoBundle\Provider\ChannelType;
16
17
class OrderRepository extends ChannelAwareEntityRepository
18
{
19
    /**
20
     * @param \DateTime $start
21
     * @param \DateTime $end
22
     * @param AclHelper $aclHelper
23
     * @return int
24
     */
25 View Code Duplication
    public function getRevenueValueByPeriod(\DateTime $start, \DateTime $end, AclHelper $aclHelper)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
26
    {
27
        $select = 'SUM(
28
             CASE WHEN orders.subtotalAmount IS NOT NULL THEN orders.subtotalAmount ELSE 0 END -
29
             CASE WHEN orders.discountAmount IS NOT NULL THEN ABS(orders.discountAmount) ELSE 0 END
30
             ) as val';
31
        $qb    = $this->createQueryBuilder('orders');
32
        $qb->select($select)
33
            ->andWhere($qb->expr()->between('orders.createdAt', ':dateStart', ':dateEnd'))
34
            ->setParameter('dateStart', $start)
35
            ->setParameter('dateEnd', $end);
36
        $this->applyActiveChannelLimitation($qb);
37
38
        $value = $aclHelper->apply($qb)->getOneOrNullResult();
39
40
        return $value['val'] ? : 0;
41
    }
42
43
    /**
44
     * @param \DateTime $start
45
     * @param \DateTime $end
46
     * @param AclHelper $aclHelper
47
     * @return int
48
     */
49 View Code Duplication
    public function getOrdersNumberValueByPeriod(\DateTime $start, \DateTime $end, AclHelper $aclHelper)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
50
    {
51
        $qb    = $this->createQueryBuilder('o');
52
        $qb->select('count(o.id) as val')
53
            ->andWhere($qb->expr()->between('o.createdAt', ':dateStart', ':dateEnd'))
54
            ->setParameter('dateStart', $start)
55
            ->setParameter('dateEnd', $end);
56
        $this->applyActiveChannelLimitation($qb);
57
58
        $value = $aclHelper->apply($qb)->getOneOrNullResult();
59
60
        return $value['val'] ? : 0;
61
    }
62
63
    /**
64
     * get Average Order Amount by given period
65
     *
66
     * @param \DateTime $start
67
     * @param \DateTime $end
68
     * @param AclHelper $aclHelper
69
     * @return int
70
     */
71 View Code Duplication
    public function getAOVValueByPeriod(\DateTime $start, \DateTime $end, AclHelper $aclHelper)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
72
    {
73
        $select = 'SUM(
74
             CASE WHEN o.subtotalAmount IS NOT NULL THEN o.subtotalAmount ELSE 0 END -
75
             CASE WHEN o.discountAmount IS NOT NULL THEN ABS(o.discountAmount) ELSE 0 END
76
             ) as revenue,
77
             count(o.id) as ordersCount';
78
        $qb    = $this->createQueryBuilder('o');
79
        $qb->select($select)
80
            ->andWhere($qb->expr()->between('o.createdAt', ':dateStart', ':dateEnd'))
81
            ->setParameter('dateStart', $start)
82
            ->setParameter('dateEnd', $end);
83
        $this->applyActiveChannelLimitation($qb);
84
85
        $value = $aclHelper->apply($qb)->getOneOrNullResult();
86
87
        return $value['revenue'] ? $value['revenue'] / $value['ordersCount'] : 0;
88
    }
89
90
    /**
91
     * @param \DateTime $start
92
     * @param \DateTime $end
93
     * @param AclHelper $aclHelper
94
     * @return float|int
95
     * @throws \Doctrine\ORM\NonUniqueResultException
96
     */
97 View Code Duplication
    public function getDiscountedOrdersPercentByDatePeriod(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
98
        \DateTime $start,
99
        \DateTime $end,
100
        AclHelper $aclHelper
101
    ) {
102
        $qb = $this->createQueryBuilder('o');
103
        $qb->select(
104
            'COUNT(o.id) as allOrders',
105
            'SUM(CASE WHEN (o.discountAmount IS NOT NULL AND o.discountAmount <> 0) THEN 1 ELSE 0 END) as discounted'
106
        );
107
        $qb->andWhere($qb->expr()->between('o.createdAt', ':dateStart', ':dateEnd'));
108
        $qb->setParameter('dateStart', $start);
109
        $qb->setParameter('dateEnd', $end);
110
        $this->applyActiveChannelLimitation($qb);
111
112
        $value = $aclHelper->apply($qb)->getOneOrNullResult();
113
        return $value['allOrders'] ? $value['discounted'] / $value['allOrders'] : 0;
114
    }
115
116
    /**
117
     * @param Cart|Customer $item
118
     * @param string        $field
119
     *
120
     * @return Cart|Customer|null $item
121
     * @throws InvalidEntityException
122
     */
123
    public function getLastPlacedOrderBy($item, $field)
124
    {
125
        if (!($item instanceof Cart) && !($item instanceof Customer)) {
126
            throw new InvalidEntityException();
127
        }
128
        $qb = $this->createQueryBuilder('o');
129
        $qb->where('o.' . $field . ' = :item');
130
        $qb->setParameter('item', $item);
131
        $qb->orderBy('o.updatedAt', 'DESC');
132
        $qb->setMaxResults(1);
133
        $this->applyActiveChannelLimitation($qb);
134
135
        return $qb->getQuery()->getOneOrNullResult();
136
    }
137
138
    /**
139
     * @param AclHelper  $aclHelper
140
     * @param \DateTime  $dateFrom
141
     * @param \DateTime  $dateTo
142
     * @param DateHelper $dateHelper
143
     * @return array
144
     */
145
    public function getAverageOrderAmount(
146
        AclHelper $aclHelper,
147
        \DateTime $dateFrom,
148
        \DateTime $dateTo,
149
        DateHelper $dateHelper
150
    ) {
151
        /** @var EntityManager $entityManager */
152
        $entityManager = $this->getEntityManager();
153
        $channels      = $entityManager->getRepository('OroCRMChannelBundle:Channel')
154
            ->getAvailableChannelNames($aclHelper, ChannelType::TYPE);
155
156
        // execute data query
157
        $queryBuilder = $this->createQueryBuilder('o');
158
        $selectClause = '
159
            IDENTITY(o.dataChannel) AS dataChannelId,
160
            AVG(
161
                CASE WHEN o.subtotalAmount IS NOT NULL THEN o.subtotalAmount ELSE 0 END -
162
                CASE WHEN o.discountAmount IS NOT NULL THEN ABS(o.discountAmount) ELSE 0 END
163
            ) as averageOrderAmount';
164
165
        $dates = $dateHelper->getDatePeriod($dateFrom, $dateTo);
166
167
        $queryBuilder->select($selectClause)
168
            ->andWhere($queryBuilder->expr()->between('o.createdAt', ':dateStart', ':dateEnd'))
169
            ->setParameter('dateStart', $dateFrom)
170
            ->setParameter('dateEnd', $dateTo)
171
            ->groupBy('dataChannelId');
172
173
        $this->applyActiveChannelLimitation($queryBuilder);
174
        $dateHelper->addDatePartsSelect($dateFrom, $dateTo, $queryBuilder, 'o.createdAt');
175
        $amountStatistics = $aclHelper->apply($queryBuilder)->getArrayResult();
176
177
        $items = [];
178
        foreach ($amountStatistics as $row) {
179
            $key         = $dateHelper->getKey($dateFrom, $dateTo, $row);
180
            $channelId   = (int)$row['dataChannelId'];
181
            $channelName = $channels[$channelId]['name'];
182
183
            if (!isset($items[$channelName])) {
184
                $items[$channelName] = $dates;
185
            }
186
            $items[$channelName][$key]['amount'] = (float)$row['averageOrderAmount'];
187
        }
188
189
        // restore default keys
190
        foreach ($items as $channelName => $item) {
191
            $items[$channelName] = array_values($item);
192
        }
193
194
        return $items;
195
    }
196
197
    /**
198
     * @param AclHelper      $aclHelper ,
199
     * @param DateHelper     $dateHelper
200
     * @param \DateTime      $from
201
     * @param \DateTime|null $to
202
     *
203
     * @return array
204
     */
205 View Code Duplication
    public function getOrdersOverTime(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
        AclHelper $aclHelper,
207
        DateHelper $dateHelper,
208
        \DateTime $from,
209
        \DateTime $to = null
210
    ) {
211
        $from = clone $from;
212
        $to   = clone $to;
213
214
        $qb = $this->createQueryBuilder('o')
215
            ->select('COUNT(o.id) AS cnt');
216
217
        $dateHelper->addDatePartsSelect($from, $to, $qb, 'o.createdAt');
218
        if ($to) {
219
            $qb->andWhere($qb->expr()->between('o.createdAt', ':from', ':to'))
220
                ->setParameter('to', $to);
221
        } else {
222
            $qb->andWhere('o.createdAt > :from');
223
        }
224
        $qb->setParameter('from', $from);
225
        $this->applyActiveChannelLimitation($qb);
226
227
        return $aclHelper->apply($qb)->getResult();
228
    }
229
230
    /**
231
     * @param AclHelper      $aclHelper
232
     * @param DateHelper     $dateHelper
233
     * @param \DateTime      $from
234
     * @param \DateTime|null $to
235
     *
236
     * @return array
237
     */
238 View Code Duplication
    public function getRevenueOverTime(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
239
        AclHelper $aclHelper,
240
        DateHelper $dateHelper,
241
        \DateTime $from,
242
        \DateTime $to = null
243
    ) {
244
        $from = clone $from;
245
        $to   = clone $to;
246
247
        $qb = $this->createQueryBuilder('o')
248
            ->select('SUM(
249
                    CASE WHEN o.subtotalAmount IS NOT NULL THEN o.subtotalAmount ELSE 0 END -
250
                    CASE WHEN o.discountAmount IS NOT NULL THEN ABS(o.discountAmount) ELSE 0 END
251
                ) AS amount');
252
253
        $dateHelper->addDatePartsSelect($from, $to, $qb, 'o.createdAt');
254
255
        if ($to) {
256
            $qb->andWhere($qb->expr()->between('o.createdAt', ':from', ':to'))
257
                ->setParameter('to', $to);
258
        } else {
259
            $qb->andWhere('o.createdAt > :from');
260
        }
261
        $qb->setParameter('from', $from);
262
        $this->applyActiveChannelLimitation($qb);
263
264
        return $aclHelper->apply($qb)->getResult();
265
    }
266
267
    /**
268
     * @param AclHelper $aclHelper
269
     * @param \DateTime $from
270
     * @param \DateTime $to
271
     *
272
     * @return int
273
     */
274 View Code Duplication
    public function getUniqueBuyersCount(AclHelper $aclHelper, \DateTime $from = null, \DateTime $to = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
275
    {
276
        $qb = $this->createQueryBuilder('o');
277
278
        try {
279
            $qb->select('COUNT(DISTINCT o.customer) + SUM(CASE WHEN o.isGuest = true THEN 1 ELSE 0 END)');
280
            if ($from) {
281
                $qb
282
                    ->andWhere('o.createdAt > :from')
283
                    ->setParameter('from', $from);
284
            }
285
            if ($to) {
286
                $qb
287
                    ->andWhere('o.createdAt > :to')
288
                    ->setParameter('to', $to);
289
            }
290
            $this->applyActiveChannelLimitation($qb);
291
292
            return (int) $aclHelper->apply($qb)->getSingleScalarResult();
293
        } catch (NoResultException $ex) {
294
            return 0;
295
        }
296
    }
297
298
    /**
299
     * @param $alias
300
     *
301
     * @return QueryBuilder
302
     */
303 View Code Duplication
    public function getUniqueCustomersCountQB($alias)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304
    {
305
        $qb = $this->createQueryBuilder($alias)
306
            ->select(
307
                sprintf(
308
                    'COUNT(DISTINCT %s.customer) + SUM(CASE WHEN %s.isGuest = true THEN 1 ELSE 0 END)',
309
                    $alias,
310
                    $alias
311
                )
312
            );
313
        $this->applyActiveChannelLimitation($qb);
314
315
        return $qb;
316
    }
317
318
    /**
319
     * @return QueryBuilder
320
     */
321
    public function getRevenueValueQB()
322
    {
323
        $select = 'SUM(
324
             CASE WHEN orders.subtotalAmount IS NOT NULL THEN orders.subtotalAmount ELSE 0 END -
325
             CASE WHEN orders.discountAmount IS NOT NULL THEN ABS(orders.discountAmount) ELSE 0 END
326
             ) as val';
327
        $qb     = $this->createQueryBuilder('orders');
328
        $qb->select($select);
329
330
        $this->applyActiveChannelLimitation($qb);
331
        
332
        return $qb;
333
    }
334
335
    /**
336
     * @return QueryBuilder
337
     */
338
    public function getOrdersNumberValueQB()
339
    {
340
        $qb = $this->createQueryBuilder('o');
341
        $qb->select('count(o.id) as val');
342
343
        $this->applyActiveChannelLimitation($qb);
344
345
        return $qb;
346
    }
347
348
    /**
349
     * @return QueryBuilder
350
     */
351
    public function getAOVValueQB()
352
    {
353
        $select = 'SUM(
354
             CASE WHEN o.subtotalAmount IS NOT NULL THEN o.subtotalAmount ELSE 0 END -
355
             CASE WHEN o.discountAmount IS NOT NULL THEN ABS(o.discountAmount) ELSE 0 END
356
             ) as revenue,
357
             count(o.id) as ordersCount';
358
        $qb     = $this->createQueryBuilder('o');
359
        $qb->select($select);
360
        $this->applyActiveChannelLimitation($qb);
361
362
        return $qb;
363
    }
364
365
    /**
366
     * @return QueryBuilder
367
     */
368
    public function getDiscountedOrdersPercentQB()
369
    {
370
        $qb = $this->createQueryBuilder('o');
371
        $qb->select(
372
            'COUNT(o.id) as allOrders',
373
            'SUM(CASE WHEN (o.discountAmount IS NOT NULL AND o.discountAmount <> 0) THEN 1 ELSE 0 END) as discounted'
374
        );
375
        $this->applyActiveChannelLimitation($qb);
376
        
377
        return $qb;
378
    }
379
}
380