Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.58% covered (warning)
85.58%
89 / 104
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReportWaitingService
85.58% covered (warning)
85.58%
89 / 104
0.00% covered (danger)
0.00%
0 / 7
30.35
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
89.47% covered (warning)
89.47%
17 / 19
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 $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 $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 ($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            $exchangeWaiting = \App::$http
93                ->readGetResult('/warehouse/waitingscope/' . $scopeId . '/' . $period . '/')
94                ->getEntity()
95                ->toGrouped($this->groupfields, $this->hashset);
96
97            $exchangeWaiting = ReportHelper::withTotalCustomers($exchangeWaiting);
98
99            $exchangeWaiting = $exchangeWaiting
100                ->withMaxByHour($this->hashset)
101                ->withMaxAndAverageFromWaitingTime();
102
103            // Apply extra ReportHelper processing
104            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime');
105            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime_termin');
106            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime');
107            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime_termin');
108
109            // per-date max/avg for total
110            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime_total');
111            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime_total');
112
113            // global max/avg for total
114            $exchangeWaiting = ReportHelper::withGlobalMaxAndAverage($exchangeWaiting, 'waitingtime_total');
115            $exchangeWaiting = ReportHelper::withGlobalMaxAndAverage($exchangeWaiting, 'waytime_total');
116
117            return $exchangeWaiting;
118        } catch (Exception $exception) {
119            return null;
120        }
121    }
122
123    /**
124     * Get waiting period data for the current scope
125     */
126    public function getWaitingPeriod(string $scopeId): mixed
127    {
128        try {
129            return \App::$http
130                ->readGetResult('/warehouse/waitingscope/' . $scopeId . '/')
131                ->getEntity();
132        } catch (Exception $exception) {
133            return null;
134        }
135    }
136
137    /**
138     * Fetch and combine data from multiple years
139     */
140    private function fetchAndCombineDataFromYears(ReportHelper $reportHelper, string $scopeId, array $years, string $fromDate, string $toDate): array
141    {
142        $combinedData = [];
143        $baseEntity = null;
144
145        foreach ($years as $year) {
146            $bounds = $reportHelper->getYearDateBounds($year, $fromDate, $toDate);
147            if ($bounds === null) {
148                continue;
149            }
150            try {
151                $exchangeWaiting = \App::$http
152                    ->readGetResult(
153                        '/warehouse/waitingscope/' . $scopeId . '/' . $year . '/',
154                        [
155                            'groupby' => 'day',
156                            'fromDate' => $bounds['from'],
157                            'toDate' => $bounds['to'],
158                        ]
159                    )
160                    ->getEntity();
161
162                if (isset($exchangeWaiting->data) && is_array($exchangeWaiting->data)) {
163                    $combinedData = array_merge($combinedData, $exchangeWaiting->data);
164                }
165
166                if ($baseEntity === null) {
167                    unset($exchangeWaiting->data);
168                    $baseEntity = $exchangeWaiting;
169                }
170            } catch (Exception $exception) {
171                // continue with other years
172            }
173        }
174
175        return [
176            'entity' => $baseEntity,
177            'data' => $combinedData
178        ];
179    }
180
181    /**
182     * Create filtered exchange waiting with updated properties
183     */
184    private function createFilteredExchangeWaiting(
185        $exchangeWaitingBasic,
186        array $filteredData,
187        string $fromDate,
188        string $toDate
189    ): mixed {
190        $exchangeWaiting = $exchangeWaitingBasic;
191        $exchangeWaiting->data = $filteredData;
192
193        if (!isset($exchangeWaiting->period)) {
194            $exchangeWaiting->period = 'day';
195        }
196
197        $exchangeWaiting->firstDay = (new Day())->setDateTime(new DateTime($fromDate));
198        $exchangeWaiting->lastDay = (new Day())->setDateTime(new DateTime($toDate));
199
200        if (!empty($filteredData)) {
201            $exchangeWaiting = $exchangeWaiting
202                ->toGrouped($this->groupfields, $this->hashset);
203
204            $exchangeWaiting = ReportHelper::withTotalCustomers($exchangeWaiting);
205
206            $exchangeWaiting = $exchangeWaiting->withMaxByHour($this->hashset)
207                ->withMaxAndAverageFromWaitingTime();
208
209            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime');
210            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime_termin');
211            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime');
212            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime_termin');
213
214            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waitingtime_total');
215            $exchangeWaiting = ReportHelper::withMaxAndAverage($exchangeWaiting, 'waytime_total');
216            $exchangeWaiting = ReportHelper::withGlobalMaxAndAverage($exchangeWaiting, 'waitingtime_total');
217            $exchangeWaiting = ReportHelper::withGlobalMaxAndAverage($exchangeWaiting, 'waytime_total');
218
219            return $exchangeWaiting;
220        }
221
222        return $exchangeWaiting->toHashed();
223    }
224
225    /**
226     * Prepare download arguments for waiting report
227     */
228    public function prepareDownloadArgs(
229        array $args,
230        mixed $exchangeWaiting,
231        ?array $dateRange,
232        array $selectedScopes = []
233    ): array {
234        $args['category'] = 'waitingscope';
235
236        if ($dateRange) {
237            $args['period'] = $dateRange['from'] . '_' . $dateRange['to'];
238        }
239
240        if (!empty($selectedScopes)) {
241            $args['selectedScopes'] = $selectedScopes;
242        }
243
244        if ($exchangeWaiting && count($exchangeWaiting->data)) {
245            $args['reports'][] = $exchangeWaiting;
246        }
247
248        return $args;
249    }
250}