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

SalesDataProvider::getSalesSummary()   C

Complexity

Conditions 10
Paths 17

Size

Total Lines 141

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 141
rs 6.1333
c 0
b 0
f 0
cc 10
nc 17
nop 4

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Component\Core\Dashboard;
15
16
use Doctrine\ORM\EntityRepository;
17
use Sylius\Component\Core\Model\ChannelInterface;
18
use Sylius\Component\Core\OrderPaymentStates;
19
20
/**
21
 * @experimental
22
 */
23
final class SalesDataProvider implements SalesDataProviderInterface
24
{
25
    /** @var EntityRepository */
26
    private $orderRepository;
27
28
    public function __construct(EntityRepository $orderRepository)
29
    {
30
        $this->orderRepository = $orderRepository;
31
    }
32
33
    function getSalesSummary(
34
        ChannelInterface $channel,
35
        \DateTimeInterface $startDate,
36
        \DateTimeInterface $endDate,
37
        Interval $interval
38
    ): SalesSummaryInterface {
39
        $queryBuilder = $this->orderRepository->createQueryBuilder('o')
40
            ->select('SUM(o.total) AS total')
41
            ->andWhere('o.paymentState = :state')
42
            ->andWhere('o.channel = :channel')
43
            ->setParameter('state', OrderPaymentStates::STATE_PAID)
44
            ->setParameter('channel', $channel)
45
        ;
46
47
        switch ($interval->asString()) {
48
            case 'year':
49
                $queryBuilder
50
                    ->addSelect('YEAR(o.checkoutCompletedAt) as year')
51
                    ->groupBy('year')
52
                    ->andHaving('year >= :startYear AND year <= :endYear')
53
                    ->setParameter('startYear', $startDate->format('Y'))
54
                    ->setParameter('endYear', $endDate->format('Y'))
55
                ;
56
                $dateFormatter = static function (\DateTimeInterface $date): string {
57
                    return $date->format('Y');
58
                };
59
                $resultFormatter = static function (array $data): string {
60
                    return $data['year'];
61
                };
62
                break;
63
64
            case 'month':
65
                $queryBuilder
66
                    ->addSelect('YEAR(o.checkoutCompletedAt) as year')
67
                    ->addSelect('MONTH(o.checkoutCompletedAt) as month')
68
                    ->groupBy('year')
69
                    ->addGroupBy('month')
70
                    ->andHaving($queryBuilder->expr()->orX(
71
                        'year = :startYear AND year = :endYear AND month >= :startMonth AND month <= :endMonth',
72
                        'year = :startYear AND year != :endYear AND month >= :startMonth',
73
                        'year = :endYear AND year != :startYear AND month <= :endMonth',
74
                        'year > :startYear AND year < :endYear'
75
                    ))
76
                    ->setParameter('startYear', $startDate->format('Y'))
77
                    ->setParameter('startMonth', $startDate->format('n'))
78
                    ->setParameter('endYear', $endDate->format('Y'))
79
                    ->setParameter('endMonth', $endDate->format('n'))
80
                ;
81
                $dateFormatter = static function (\DateTimeInterface $date): string {
82
                    return $date->format('n.Y');
83
                };
84
                $resultFormatter = static function (array $data): string {
85
                    return $data['month'] . '.' . $data['year'];
86
                };
87
                break;
88
89
            case 'week':
90
                $queryBuilder
91
                    ->addSelect('YEAR(o.checkoutCompletedAt) as year')
92
                    ->addSelect('WEEK(o.checkoutCompletedAt) as week')
93
                    ->groupBy('year')
94
                    ->addGroupBy('week')
95
                    ->andHaving($queryBuilder->expr()->orX(
96
                        'year = :startYear AND year = :endYear AND week >= :startWeek AND week <= :endWeek',
97
                        'year = :startYear AND year != :endYear AND week >= :startWeek',
98
                        'year = :endYear AND year != :startYear AND week <= :endWeek',
99
                        'year > :startYear AND year < :endYear'
100
                    ))
101
                    ->setParameter('startYear', $startDate->format('Y'))
102
                    ->setParameter('startWeek', (ltrim($startDate->format('W'), '0') ?: '0'))
103
                    ->setParameter('endYear', $endDate->format('Y'))
104
                    ->setParameter('endWeek', (ltrim($endDate->format('W'), '0') ?: '0'))
105
                ;
106
                $dateFormatter = static function (\DateTimeInterface $date): string {
107
                    return (ltrim($date->format('W'), '0') ?: '0') . ' ' . $date->format('Y');
108
                };
109
                $resultFormatter = static function (array $data): string {
110
                    return $data['week'] . ' ' . $data['year'];
111
                };
112
                break;
113
114
            case 'day':
115
                $queryBuilder
116
                    ->addSelect('YEAR(o.checkoutCompletedAt) as year')
117
                    ->addSelect('MONTH(o.checkoutCompletedAt) as month')
118
                    ->addSelect('DAY(o.checkoutCompletedAt) as day')
119
                    ->groupBy('year')
120
                    ->addGroupBy('month')
121
                    ->addGroupBy('day')
122
                    ->andHaving($queryBuilder->expr()->orX(
123
                        'year = :startYear AND year = :endYear AND month = :startMonth AND month = :endMonth AND day >= :startDay AND day <= :endDay',
124
                        'year = :startYear AND year = :endYear AND month = :startMonth AND month != :endMonth AND day >= :startDay',
125
                        'year = :startYear AND year = :endYear AND month = :endMonth AND month != :startMonth AND day <= :endDay',
126
                        'year = :startYear AND year = :endYear AND month > :startMonth AND month < :endMonth',
127
                        'year = :startYear AND year != :endYear AND month = :startMonth AND day >= :startDay',
128
                        'year = :startYear AND year != :endYear AND month > :startMonth',
129
                        'year = :endYear AND year != :startYear AND month = :endMonth AND day <= :endDay',
130
                        'year = :endYear AND year != :startYear AND month < :endMonth',
131
                        'year > :startYear AND year < :endYear'
132
                    ))
133
                    ->setParameter('startYear', $startDate->format('Y'))
134
                    ->setParameter('startMonth', $startDate->format('n'))
135
                    ->setParameter('startDay', $startDate->format('j'))
136
                    ->setParameter('endYear', $endDate->format('Y'))
137
                    ->setParameter('endMonth', $endDate->format('n'))
138
                    ->setParameter('endDay', $endDate->format('j'))
139
                ;
140
                $dateFormatter = static function (\DateTimeInterface $date): string {
141
                    return $date->format('j.n.Y');
142
                };
143
                $resultFormatter = static function (array $data): string {
144
                    return $data['day'] . '.' . $data['month'] . '.' . $data['year'];
145
                };
146
                break;
147
148
            default:
149
                throw new \RuntimeException(sprintf('Interval "%s" not supported.', $interval->asString()));
150
        }
151
152
        $ordersTotals = $queryBuilder->getQuery()->getArrayResult();
153
154
        $salesData = [];
155
156
        $period = new \DatePeriod($startDate, \DateInterval::createFromDateString(sprintf('1 %s', $interval->asString())), $endDate);
157
        foreach ($period as $date) {
158
            $salesData[$dateFormatter($date)] = 0;
159
        }
160
161
        foreach ($ordersTotals as $item) {
162
            $salesData[$resultFormatter($item)] = (int) $item['total'];
163
        }
164
165
        $salesData = array_map(
166
            static function (int $total): string {
167
                return number_format(abs($total / 100), 2, '.', '');
168
            },
169
            $salesData
170
        );
171
172
        return new SalesSummary($salesData);
173
    }
174
}
175