Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
84.52% covered (warning)
84.52%
71 / 84
14.29% covered (danger)
14.29%
1 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReportRequestService
84.52% covered (warning)
84.52%
71 / 84
14.29% covered (danger)
14.29%
1 / 7
29.70
0.00% covered (danger)
0.00%
0 / 1
 getExchangeRequestData
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getExchangeRequestForDateRange
76.47% covered (warning)
76.47%
13 / 17
0.00% covered (danger)
0.00%
0 / 1
5.33
 getExchangeRequestForPeriod
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
2.06
 getRequestPeriod
60.00% covered (warning)
60.00%
3 / 5
0.00% covered (danger)
0.00%
0 / 1
2.26
 fetchAndCombineDataFromYears
95.45% covered (success)
95.45%
21 / 22
0.00% covered (danger)
0.00%
0 / 1
6
 createFilteredExchangeRequest
89.47% covered (warning)
89.47%
17 / 19
0.00% covered (danger)
0.00%
0 / 1
4.02
 prepareDownloadArgs
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
5.39
1<?php
2
3/**
4 * @package Zmsstatistic
5 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
6 **/
7
8namespace BO\Zmsstatistic\Service;
9
10use BO\Zmsentities\Day;
11use BO\Zmsstatistic\Helper\ReportHelper;
12use DateTime;
13use Exception;
14
15class ReportRequestService
16{
17    protected $totals = ['requestscount'];
18
19    protected $hashset = [
20        'requestscount'
21    ];
22
23    protected $groupfields = [
24        'name',
25        'date'
26    ];
27
28    /**
29     * Get exchange request data based on date range or period
30     */
31    public function getExchangeRequestData(string $scopeId, ?array $dateRange, array $args): mixed
32    {
33        if ($dateRange) {
34            return $this->getExchangeRequestForDateRange($scopeId, $dateRange);
35        }
36
37        return isset($args['period'])
38            ? $this->getExchangeRequestForPeriod($scopeId, $args['period'])
39            : null;
40    }
41
42    /**
43     * Get exchange request data for a specific date range
44     */
45    public function getExchangeRequestForDateRange(string $scopeId, array $dateRange): mixed
46    {
47        if (!isset($dateRange['from']) || !isset($dateRange['to'])) {
48            return null;
49        }
50        $fromDate = $dateRange['from'];
51        $toDate = $dateRange['to'];
52
53        try {
54            $reportHelper = new ReportHelper();
55            $years = $reportHelper->getYearsForDateRange($fromDate, $toDate);
56            $combinedData = $this->fetchAndCombineDataFromYears($scopeId, $years, $fromDate, $toDate);
57
58            if (empty($combinedData['data'])) {
59                return null;
60            }
61
62            return $this->createFilteredExchangeRequest(
63                $combinedData['entity'],
64                $combinedData['data'],
65                $fromDate,
66                $toDate
67            );
68        } catch (Exception $exception) {
69            return null;
70        }
71    }
72
73    /**
74     * Get exchange request data for a specific period (legacy functionality)
75     */
76    public function getExchangeRequestForPeriod(string $scopeId, string $period): mixed
77    {
78        try {
79            return \App::$http
80                ->readGetResult('/warehouse/requestscope/' . $scopeId . '/' . $period . '/')
81                ->getEntity()
82                ->toGrouped($this->groupfields, $this->hashset)
83                ->withRequestsSum()
84                ->withAverage('processingtime');
85        } catch (Exception $exception) {
86            return null;
87        }
88    }
89
90    /**
91     * Get request period data for the current scope
92     */
93    public function getRequestPeriod(string $scopeId): mixed
94    {
95        try {
96            return \App::$http
97                ->readGetResult('/warehouse/requestscope/' . $scopeId . '/')
98                ->getEntity();
99        } catch (Exception $exception) {
100            return null;
101        }
102    }
103
104    /**
105     * Fetch and combine data from multiple years
106     */
107    private function fetchAndCombineDataFromYears(string $scopeId, array $years, string $fromDate, string $toDate): array
108    {
109        $combinedData = [];
110        $baseEntity = null;
111
112        foreach ($years as $year) {
113            try {
114                $exchangeRequest = \App::$http
115                    ->readGetResult(
116                        '/warehouse/requestscope/' . $scopeId . '/' . $year . '/',
117                        [
118                            'groupby' => 'day',
119                            'fromDate' => $fromDate,
120                            'toDate' => $toDate
121                        ]
122                    )
123                    ->getEntity();
124
125                // Use the first successfully fetched entity as the base
126                if ($baseEntity === null) {
127                    $baseEntity = $exchangeRequest;
128                }
129
130                // Combine data from all years
131                if (isset($exchangeRequest->data) && is_array($exchangeRequest->data)) {
132                    $combinedData = array_merge($combinedData, $exchangeRequest->data);
133                }
134            } catch (Exception $exception) {
135                // Continue with other years - don't fail completely if one year is missing
136            }
137        }
138
139        return [
140            'entity' => $baseEntity,
141            'data' => $combinedData
142        ];
143    }
144
145    /**
146     * Create filtered exchange request with updated properties
147     */
148    private function createFilteredExchangeRequest(
149        $exchangeRequestBasic,
150        array $filteredData,
151        string $fromDate,
152        string $toDate
153    ): mixed {
154        $exchangeRequest = $exchangeRequestBasic;
155        $exchangeRequest->data = $filteredData;
156
157        if (!isset($exchangeRequest->period)) {
158            $exchangeRequest->period = 'day';
159        }
160
161        $exchangeRequest->firstDay = (new Day())->setDateTime(new DateTime($fromDate));
162        $exchangeRequest->lastDay = (new Day())->setDateTime(new DateTime($toDate));
163
164        if (!empty($filteredData)) {
165            $exchangeRequest = $exchangeRequest
166                ->toGrouped($this->groupfields, $this->hashset)
167                ->withRequestsSum()
168                ->withAverage('processingtime');
169
170            if (is_array($exchangeRequest->data)) {
171                $locale = \App::$supportedLanguages[\App::$locale]['locale'] ?? 'de_DE';
172                $collator = new \Collator($locale);
173                uksort($exchangeRequest->data, static function ($itemA, $itemB) use ($collator) {
174                    return $collator->compare($itemA, $itemB);
175                });
176            }
177
178            return $exchangeRequest;
179        }
180
181        return $exchangeRequest->toHashed();
182    }
183
184    /**
185     * Prepare download arguments for request report
186     */
187    public function prepareDownloadArgs(
188        array $args,
189        mixed $exchangeRequest,
190        ?array $dateRange,
191        array $selectedScopes = []
192    ): array {
193        $args['category'] = 'requestscope';
194
195        if ($dateRange) {
196            $args['period'] = $dateRange['from'] . '_' . $dateRange['to'];
197        }
198
199        if (!empty($selectedScopes)) {
200            $args['selectedScopes'] = $selectedScopes;
201        }
202
203        if ($exchangeRequest && count($exchangeRequest->data)) {
204            $args['reports'][] = $exchangeRequest;
205        }
206
207        return $args;
208    }
209}