Completed
Push — 1.10 ( 3f8f95...f007bc )
by
unknown
09:16
created

getAvailableOpportunityStatuses()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 0
1
<?php
2
3
namespace OroCRM\Bundle\SalesBundle\Dashboard\Provider;
4
5
use Symfony\Bridge\Doctrine\RegistryInterface;
6
7
use Oro\Component\DoctrineUtils\ORM\QueryUtils;
8
9
use Oro\Bundle\DashboardBundle\Filter\DateFilterProcessor;
10
use Oro\Bundle\DashboardBundle\Model\WidgetOptionBag;
11
use Oro\Bundle\EntityExtendBundle\Entity\Repository\EnumValueRepository;
12
use Oro\Bundle\EntityExtendBundle\Tools\ExtendHelper;
13
use Oro\Bundle\SecurityBundle\ORM\Walker\AclHelper;
14
use Oro\Bundle\UserBundle\Dashboard\OwnerHelper;
15
16
use OroCRM\Bundle\SalesBundle\Entity\Repository\OpportunityRepository;
17
18
class OpportunityByStatusProvider
19
{
20
    /** @var RegistryInterface */
21
    protected $registry;
22
23
    /** @var AclHelper */
24
    protected $aclHelper;
25
26
    /** @var DateFilterProcessor */
27
    protected $dateFilterProcessor;
28
29
    /** @var OwnerHelper */
30
    protected $ownerHelper;
31
32
    /**
33
     * @param RegistryInterface   $doctrine
34
     * @param AclHelper           $aclHelper
35
     * @param DateFilterProcessor $processor
36
     * @param OwnerHelper         $ownerHelper
37
     */
38
    public function __construct(
39
        RegistryInterface $doctrine,
40
        AclHelper $aclHelper,
41
        DateFilterProcessor $processor,
42
        OwnerHelper $ownerHelper
43
    ) {
44
        $this->registry            = $doctrine;
45
        $this->aclHelper           = $aclHelper;
46
        $this->dateFilterProcessor = $processor;
47
        $this->ownerHelper         = $ownerHelper;
48
    }
49
50
    /**
51
     * @param WidgetOptionBag $widgetOptions
52
     *
53
     * @return array
54
     */
55
    public function getOpportunitiesGroupedByStatus(WidgetOptionBag $widgetOptions)
56
    {
57
        $dateRange        = $widgetOptions->get('dateRange');
58
        $owners           = $this->ownerHelper->getOwnerIds($widgetOptions);
59
        /**
60
         * Excluded statuses will be filtered from result in method `formatResult` below.
61
         * Due to performance issues with `NOT IN` clause in database.
62
         */
63
        $excludedStatuses = $widgetOptions->get('excluded_statuses', []);
64
        $orderBy          = $widgetOptions->get('useQuantityAsData') ? 'quantity' : 'budget';
65
66
        /** @var OpportunityRepository $opportunityRepository */
67
        $opportunityRepository = $this->registry->getRepository('OroCRMSalesBundle:Opportunity');
68
        $qb = $opportunityRepository->createQueryBuilder('o')
69
            ->select('IDENTITY (o.status) status')
70
            ->groupBy('status')
71
            ->orderBy($orderBy, 'DESC');
72
73
        switch ($orderBy) {
74
            case 'quantity':
75
                $qb->addSelect('COUNT(o.id) as quantity');
76
                break;
77
            case 'budget':
78
                $qb->addSelect(
79
                    'SUM(
80
                        CASE WHEN o.status = \'won\'
81
                            THEN (CASE WHEN o.closeRevenue IS NOT NULL THEN o.closeRevenue ELSE 0 END)
82
                            ELSE (CASE WHEN o.budgetAmount IS NOT NULL THEN o.budgetAmount ELSE 0 END)
83
                        END
84
                    ) as budget'
85
                );
86
        }
87
88
        $this->dateFilterProcessor->applyDateRangeFilterToQuery($qb, $dateRange, 'o.createdAt');
89
90
        if ($owners) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $owners of type integer[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
91
            QueryUtils::applyOptimizedIn($qb, 'o.owner', $owners);
92
        }
93
94
        $result = $this->aclHelper->apply($qb)->getArrayResult();
95
96
        return $this->formatResult($result, $excludedStatuses, $orderBy);
97
    }
98
99
    /**
100
     * @param array    $result
101
     * @param string[] $excludedStatuses
102
     * @param string   $orderBy
103
     *
104
     * @return array
105
     */
106
    protected function formatResult($result, $excludedStatuses, $orderBy)
107
    {
108
        $resultStatuses = array_flip(array_column($result, 'status', null));
109
110
        foreach ($this->getAvailableOpportunityStatuses() as $statusKey => $statusLabel) {
111
            $resultIndex = isset($resultStatuses[$statusKey]) ? $resultStatuses[$statusKey] : null;
112
            if (in_array($statusKey, $excludedStatuses)) {
113
                if (null !== $resultIndex) {
114
                    unset($result[$resultIndex]);
115
                }
116
                continue;
117
            }
118
119
            if (null !== $resultIndex) {
120
                $result[$resultIndex]['label'] = $statusLabel;
121
            } else {
122
                $result[] = [
123
                    'status' => $statusKey,
124
                    'label'  => $statusLabel,
125
                    $orderBy => 0
126
                ];
127
            }
128
        }
129
130
        return $result;
131
    }
132
133
    /**
134
     * @return array
135
     */
136
    protected function getAvailableOpportunityStatuses()
137
    {
138
        /** @var EnumValueRepository $statusesRepository */
139
        $statusesRepository = $this->registry->getRepository(
140
            ExtendHelper::buildEnumValueClassName('opportunity_status')
141
        );
142
        $statuses = $statusesRepository->createQueryBuilder('s')
143
            ->select('s.id, s.name')
144
            ->getQuery()
145
            ->getArrayResult();
146
147
        return array_column($statuses, 'name', 'id');
148
    }
149
}
150