Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
61.45% covered (warning)
61.45%
51 / 83
12.50% covered (danger)
12.50%
1 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReportRequestService
61.45% covered (warning)
61.45%
51 / 83
12.50% covered (danger)
12.50%
1 / 8
90.68
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
66.67% covered (warning)
66.67%
10 / 15
0.00% covered (danger)
0.00%
0 / 1
7.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
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
6.01
 filterDataByDateRange
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
4.13
 createFilteredExchangeRequest
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
20
 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        } elseif (isset($args['period'])) {
36            return $this->getExchangeRequestForPeriod($scopeId, $args['period']);
37        }
38
39        return 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);
57
58            if (empty($combinedData['data'])) {
59                return null;
60            }
61
62            $filteredData = $this->filterDataByDateRange($combinedData['data'], $fromDate, $toDate);
63
64            if (empty($filteredData)) {
65                return null;
66            }
67
68            return $this->createFilteredExchangeRequest($combinedData['entity'], $filteredData, $fromDate, $toDate);
69        } catch (Exception $exception) {
70            return null;
71        }
72    }
73
74    /**
75     * Get exchange request data for a specific period (legacy functionality)
76     */
77    public function getExchangeRequestForPeriod(string $scopeId, string $period): mixed
78    {
79        try {
80            return \App::$http
81                ->readGetResult('/warehouse/requestscope/' . $scopeId . '/' . $period . '/')
82                ->getEntity()
83                ->toGrouped($this->groupfields, $this->hashset)
84                ->withRequestsSum()
85                ->withAverage('processingtime');
86        } catch (Exception $exception) {
87            return null;
88        }
89    }
90
91    /**
92     * Get request period data for the current scope
93     */
94    public function getRequestPeriod(string $scopeId): mixed
95    {
96        try {
97            return \App::$http
98                ->readGetResult('/warehouse/requestscope/' . $scopeId . '/')
99                ->getEntity();
100        } catch (Exception $exception) {
101            return null;
102        }
103    }
104
105    /**
106     * Fetch and combine data from multiple years
107     */
108    private function fetchAndCombineDataFromYears(string $scopeId, array $years): array
109    {
110        $combinedData = [];
111        $baseEntity = null;
112
113        foreach ($years as $year) {
114            try {
115                $exchangeRequest = \App::$http
116                    ->readGetResult(
117                        '/warehouse/requestscope/' . $scopeId . '/' . $year . '/',
118                        ['groupby' => 'day']
119                    )
120                    ->getEntity();
121
122                // Use the first successfully fetched entity as the base
123                if ($baseEntity === null) {
124                    $baseEntity = $exchangeRequest;
125                }
126
127                // Combine data from all years
128                if (isset($exchangeRequest->data) && is_array($exchangeRequest->data)) {
129                    $combinedData = array_merge($combinedData, $exchangeRequest->data);
130                }
131            } catch (Exception $exception) {
132                // Continue with other years - don't fail completely if one year is missing
133            }
134        }
135
136        return [
137            'entity' => $baseEntity,
138            'data' => $combinedData
139        ];
140    }
141
142    /**
143     * Filter data array by date range
144     */
145    private function filterDataByDateRange(array $data, string $fromDate, string $toDate): array
146    {
147        $filteredData = [];
148        foreach ($data as $row) {
149            if ($row[3] >= $fromDate && $row[3] <= $toDate) {
150                $filteredData[] = $row;
151            }
152        }
153        return $filteredData;
154    }
155
156    /**
157     * Create filtered exchange request with updated properties
158     */
159    private function createFilteredExchangeRequest(
160        $exchangeRequestFull,
161        array $filteredData,
162        string $fromDate,
163        string $toDate
164    ): mixed {
165        $exchangeRequest = clone $exchangeRequestFull;
166        $exchangeRequest->data = $filteredData;
167
168        if (!isset($exchangeRequest->period)) {
169            $exchangeRequest->period = 'day';
170        }
171
172        $exchangeRequest->firstDay = (new Day())->setDateTime(new DateTime($fromDate));
173        $exchangeRequest->lastDay = (new Day())->setDateTime(new DateTime($toDate));
174
175        if (!empty($filteredData)) {
176            $exchangeRequest = $exchangeRequest
177                ->toGrouped($this->groupfields, $this->hashset)
178                ->withRequestsSum()
179                ->withAverage('processingtime');
180
181            if (is_array($exchangeRequest->data)) {
182                $locale = \App::$supportedLanguages[\App::$locale]['locale'] ?? 'de_DE';
183                $collator = new \Collator($locale);
184                uksort($exchangeRequest->data, static function ($itemA, $itemB) use ($collator) {
185                    return $collator->compare($itemA, $itemB);
186                });
187            }
188
189            return $exchangeRequest;
190        }
191
192        return $exchangeRequest->toHashed();
193    }
194
195    /**
196     * Prepare download arguments for request report
197     */
198    public function prepareDownloadArgs(
199        array $args,
200        mixed $exchangeRequest,
201        ?array $dateRange,
202        array $selectedScopes = []
203    ): array {
204        $args['category'] = 'requestscope';
205
206        if ($dateRange) {
207            $args['period'] = $dateRange['from'] . '_' . $dateRange['to'];
208        }
209
210        if (!empty($selectedScopes)) {
211            $args['selectedScopes'] = $selectedScopes;
212        }
213
214        if ($exchangeRequest && count($exchangeRequest->data)) {
215            $args['reports'][] = $exchangeRequest;
216        }
217
218        return $args;
219    }
220}