Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.71% covered (warning)
85.71%
66 / 77
37.50% covered (danger)
37.50%
3 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReportClientService
85.71% covered (warning)
85.71%
66 / 77
37.50% covered (danger)
37.50%
3 / 8
33.80
0.00% covered (danger)
0.00%
0 / 1
 getExchangeClientData
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getExchangeClientForDateRange
73.33% covered (warning)
73.33%
11 / 15
0.00% covered (danger)
0.00%
0 / 1
6.68
 getExchangeClientForPeriod
71.43% covered (warning)
71.43%
5 / 7
0.00% covered (danger)
0.00%
0 / 1
2.09
 getClientPeriod
60.00% covered (warning)
60.00%
3 / 5
0.00% covered (danger)
0.00%
0 / 1
2.26
 fetchAndCombineDataFromYears
95.24% covered (success)
95.24%
20 / 21
0.00% covered (danger)
0.00%
0 / 1
6
 filterDataByDateRange
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 createFilteredExchangeClient
81.82% covered (warning)
81.82%
9 / 11
0.00% covered (danger)
0.00%
0 / 1
3.05
 prepareDownloadArgs
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
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 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}