Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.71% covered (warning)
85.71%
90 / 105
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReportWaitingService
85.71% covered (warning)
85.71%
90 / 105
0.00% covered (danger)
0.00%
0 / 7
30.29
0.00% covered (danger)
0.00%
0 / 1
 getExchangeWaitingData
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
4.05
 getExchangeWaitingForDateRange
76.47% covered (warning)
76.47%
13 / 17
0.00% covered (danger)
0.00%
0 / 1
5.33
 getExchangeWaitingForPeriod
90.00% covered (success)
90.00%
18 / 20
0.00% covered (danger)
0.00%
0 / 1
2.00
 getWaitingPeriod
60.00% covered (warning)
60.00%
3 / 5
0.00% covered (danger)
0.00%
0 / 1
2.26
 fetchAndCombineDataFromYears
92.31% covered (success)
92.31%
24 / 26
0.00% covered (danger)
0.00%
0 / 1
7.02
 createFilteredExchangeWaiting
90.91% covered (success)
90.91%
20 / 22
0.00% covered (danger)
0.00%
0 / 1
3.01
 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 ReportWaitingService
16{
17    protected array $hashset = [
18        'waitingcount',
19        'waitingtime',
20        'waitingcalculated',
21        'waitingcount_termin',
22        'waitingtime_termin',
23        'waitingcalculated_termin',
24        'waytime',
25        'waytime_termin',
26        'waitingcount_total',
27        'waitingtime_total',
28        'waytime_total',
29    ];
30
31    protected array $groupfields = [
32        'date',
33        'hour'
34    ];
35
36    /**
37     * Get exchange waiting data based on date range or period
38     */
39    public function getExchangeWaitingData(string $scopeId, ?array $dateRange, array $args): mixed
40    {
41        if ($scopeId === '') {
42            return null;
43        }
44
45        if (ReportHelper::hasValues($dateRange)) {
46            return $this->getExchangeWaitingForDateRange($scopeId, $dateRange);
47        }
48
49        return isset($args['period'])
50            ? $this->getExchangeWaitingForPeriod($scopeId, $args['period'])
51            : null;
52    }
53
54    /**
55     * Get exchange waiting data for a specific date range
56     */
57    public function getExchangeWaitingForDateRange(string $scopeId, array $dateRange): mixed
58    {
59        if (!isset($dateRange['from']) || !isset($dateRange['to'])) {
60            return null;
61        }
62
63        $fromDate = $dateRange['from'];
64        $toDate = $dateRange['to'];
65
66        try {
67            $reportHelper = new ReportHelper();
68            $years = $reportHelper->getYearsForDateRange($fromDate, $toDate);
69            $combinedData = $this->fetchAndCombineDataFromYears($reportHelper, $scopeId, $years, $fromDate, $toDate);
70
71            if (empty($combinedData['data'])) {
72                return null;
73            }
74
75            return $this->createFilteredExchangeWaiting(
76                $combinedData['entity'],
77                $combinedData['data'],
78                $fromDate,
79                $toDate
80            );
81        } catch (Exception $exception) {
82            return null;
83        }
84    }
85
86    /**
87     * Get exchange waiting data for a specific period (legacy functionality)
88     */
89    public function getExchangeWaitingForPeriod(string $scopeId, string $period): mixed
90    {
91        try {
92            /** @var mixed $entity */
93            $entity = \App::http()
94                ->readGetResult('/warehouse/waitingscope/' . $scopeId . '/' . $period . '/')
95                ->getEntity();
96            $exchangeWaiting = $entity
97                ->toGrouped($this->groupfields, $this->hashset);
98
99            $exchangeWaiting = ReportHelper::withTotalCustomers($exchangeWaiting);
100
101            $exchangeWaiting = $exchangeWaiting
102                ->withMaxByHour($this->hashset)
103                ->withMaxAndAverageFromWaitingTime();
104
105            // Apply extra ReportHelper processing
106            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime');
107            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime_termin');
108            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime');
109            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime_termin');
110
111            // per-date max/avg for total
112            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime_total');
113            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime_total');
114
115            // global max/avg for total
116            $exchangeWaiting = ReportHelper::withGlobalMaxAndAverage($exchangeWaiting, 'waitingtime_total');
117            $exchangeWaiting = ReportHelper::withGlobalMaxAndAverage($exchangeWaiting, 'waytime_total');
118
119            return $exchangeWaiting;
120        } catch (Exception $exception) {
121            return null;
122        }
123    }
124
125    /**
126     * Get waiting period data for the current scope
127     */
128    public function getWaitingPeriod(string $scopeId): mixed
129    {
130        try {
131            return \App::http()
132                ->readGetResult('/warehouse/waitingscope/' . $scopeId . '/')
133                ->getEntity();
134        } catch (Exception $exception) {
135            return null;
136        }
137    }
138
139    /**
140     * Fetch and combine data from multiple years
141     */
142    private function fetchAndCombineDataFromYears(ReportHelper $reportHelper, string $scopeId, array $years, string $fromDate, string $toDate): array
143    {
144        $combinedData = [];
145        $baseEntity = null;
146
147        foreach ($years as $year) {
148            $bounds = $reportHelper->getYearDateBounds($year, $fromDate, $toDate);
149            if ($bounds === null) {
150                continue;
151            }
152            try {
153                $exchangeWaiting = \App::http()
154                    ->readGetResult(
155                        '/warehouse/waitingscope/' . $scopeId . '/' . $year . '/',
156                        [
157                            'groupby' => 'day',
158                            'fromDate' => $bounds['from'],
159                            'toDate' => $bounds['to'],
160                        ]
161                    )
162                    ->getEntity();
163
164                if (isset($exchangeWaiting->data) && is_array($exchangeWaiting->data)) {
165                    $combinedData = array_merge($combinedData, $exchangeWaiting->data);
166                }
167
168                if ($baseEntity === null) {
169                    unset($exchangeWaiting->data);
170                    $baseEntity = $exchangeWaiting;
171                }
172            } catch (Exception $exception) {
173                // continue with other years
174            }
175        }
176
177        return [
178            'entity' => $baseEntity,
179            'data' => $combinedData
180        ];
181    }
182
183    /**
184     * Create filtered exchange waiting with updated properties
185     */
186    private function createFilteredExchangeWaiting(
187        mixed $exchangeWaitingBasic,
188        array $filteredData,
189        string $fromDate,
190        string $toDate
191    ): mixed {
192        $exchangeWaiting = $exchangeWaitingBasic;
193        $exchangeWaiting->data = $filteredData;
194
195        if (!isset($exchangeWaiting->period)) {
196            $exchangeWaiting->period = 'day';
197        }
198
199        $exchangeWaiting->firstDay = (new Day())->setDateTime(new DateTime($fromDate));
200        $exchangeWaiting->lastDay = (new Day())->setDateTime(new DateTime($toDate));
201
202        if (!empty($filteredData)) {
203            $exchangeWaiting = $exchangeWaiting
204                ->toGrouped($this->groupfields, $this->hashset);
205
206            $exchangeWaiting = ReportHelper::withTotalCustomers($exchangeWaiting);
207
208            $exchangeWaiting = $exchangeWaiting->withMaxByHour($this->hashset)
209                ->withMaxAndAverageFromWaitingTime();
210
211            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime');
212            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime_termin');
213            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime');
214            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime_termin');
215
216            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime_total');
217            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime_total');
218            $exchangeWaiting = ReportHelper::withGlobalMaxAndAverage($exchangeWaiting, 'waitingtime_total');
219            $exchangeWaiting = ReportHelper::withGlobalMaxAndAverage($exchangeWaiting, 'waytime_total');
220
221            return $exchangeWaiting;
222        }
223
224        return $exchangeWaiting->toHashed();
225    }
226
227    /**
228     * Prepare download arguments for waiting report
229     */
230    public function prepareDownloadArgs(
231        array $args,
232        mixed $exchangeWaiting,
233        ?array $dateRange,
234        array $selectedScopes = []
235    ): array {
236        $args['category'] = 'waitingscope';
237
238        if (ReportHelper::hasValues($dateRange)) {
239            $args['period'] = $dateRange['from'] . '_' . $dateRange['to'];
240        }
241
242        if (!empty($selectedScopes)) {
243            $args['selectedScopes'] = $selectedScopes;
244        }
245
246        if ($exchangeWaiting && count($exchangeWaiting->data)) {
247            $args['reports'][] = $exchangeWaiting;
248        }
249
250        return $args;
251    }
252}