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