Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.75% covered (warning)
86.75%
72 / 83
14.29% covered (danger)
14.29%
1 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReportClientService
86.75% covered (warning)
86.75%
72 / 83
14.29% covered (danger)
14.29%
1 / 7
29.82
0.00% covered (danger)
0.00%
0 / 1
 getExchangeClientData
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 getExchangeClientForDateRange
82.35% covered (warning)
82.35%
14 / 17
0.00% covered (danger)
0.00%
0 / 1
5.14
 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
96.43% covered (success)
96.43%
27 / 28
0.00% covered (danger)
0.00%
0 / 1
7
 createFilteredExchangeClient
81.82% covered (warning)
81.82%
9 / 11
0.00% covered (danger)
0.00%
0 / 1
3.05
 prepareDownloadArgs
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
5.05
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 DateTimeImmutable;
14use Exception;
15
16class ReportClientService
17{
18    protected $totals = [
19        'clientscount',
20        'missed',
21        'withappointment',
22        'missedwithappointment',
23        'noappointment',
24        'missednoappointment',
25        'ticketprinter',
26        'ticketprintermissed',
27        'requestscount'
28    ];
29
30    /**
31     * Get exchange client data based on date range or period
32     */
33    public function getExchangeClientData(string $scopeId, ?array $dateRange, array $args): mixed
34    {
35        if ($scopeId === '') {
36            return null;
37        }
38
39        if ($dateRange) {
40            return $this->getExchangeClientForDateRange($scopeId, $dateRange);
41        }
42
43        return isset($args['period'])
44            ? $this->getExchangeClientForPeriod($scopeId, $args['period'])
45            : null;
46    }
47
48    /**
49     * Get exchange client data for a specific date range
50     */
51    public function getExchangeClientForDateRange(string $scopeId, array $dateRange): mixed
52    {
53        if (!isset($dateRange['from']) || !isset($dateRange['to'])) {
54            return null;
55        }
56        $fromDate = $dateRange['from'];
57        $toDate = $dateRange['to'];
58
59        try {
60            $reportHelper = new ReportHelper();
61            $years = $reportHelper->getYearsForDateRange($fromDate, $toDate);
62            $combinedData = $this->fetchAndCombineDataFromYears($reportHelper, $scopeId, $years, $fromDate, $toDate);
63
64            if (empty($combinedData['data'])) {
65                return null;
66            }
67
68            return $this->createFilteredExchangeClient(
69                $combinedData['entity'],
70                $combinedData['data'],
71                $fromDate,
72                $toDate
73            );
74        } catch (Exception $exception) {
75            return null;
76        }
77    }
78
79    /**
80     * Get exchange client data for a specific period (legacy functionality)
81     */
82    public function getExchangeClientForPeriod(string $scopeId, string $period): mixed
83    {
84        try {
85            return \App::$http
86                ->readGetResult('/warehouse/clientscope/' . $scopeId . '/' . $period . '/')
87                ->getEntity()
88                ->withCalculatedTotals($this->totals, 'date')
89                ->toHashed();
90        } catch (Exception $exception) {
91            return null;
92        }
93    }
94
95    /**
96     * Get client period data for the current scope
97     */
98    public function getClientPeriod(string $scopeId): mixed
99    {
100        try {
101            return \App::$http
102                ->readGetResult('/warehouse/clientscope/' . $scopeId . '/')
103                ->getEntity();
104        } catch (Exception $exception) {
105            return null;
106        }
107    }
108
109    /**
110     * Fetch and combine data from multiple years
111     */
112    private function fetchAndCombineDataFromYears(ReportHelper $reportHelper, string $scopeId, array $years, string $fromDate, string $toDate): array
113    {
114        $combinedData = [];
115        $baseEntity = null;
116
117        foreach ($years as $year) {
118            $bounds = $reportHelper->getYearDateBounds($year, $fromDate, $toDate);
119            if ($bounds === null) {
120                continue;
121            }
122            try {
123                $exchangeClient = \App::$http
124                    ->readGetResult(
125                        '/warehouse/clientscope/' . $scopeId . '/' . $year . '/',
126                        [
127                            'groupby' => 'day',
128                            'fromDate' => $bounds['from'],
129                            'toDate' => $bounds['to'],
130                        ]
131                    )
132                    ->getEntity();
133
134                // Use the first successfully fetched entity as the base
135                if ($baseEntity === null) {
136                    $baseEntity = $exchangeClient;
137                }
138
139                // Combine data from all years
140                if (isset($exchangeClient->data) && is_array($exchangeClient->data)) {
141                    $combinedData = array_merge($combinedData, $exchangeClient->data);
142                }
143            } catch (Exception $exception) {
144                // Continue with other years - don't fail completely if one year is missing
145            }
146        }
147
148        usort($combinedData, static function ($a, $b) {
149            return strcmp($a[1] ?? '', $b[1] ?? '');
150        });
151
152        return [
153            'entity' => $baseEntity,
154            'data' => $combinedData
155        ];
156    }
157
158    /**
159     * Create filtered exchange client with updated properties
160     */
161    private function createFilteredExchangeClient(
162        $exchangeClientBasic,
163        array $filteredData,
164        string $fromDate,
165        string $toDate
166    ): mixed {
167        $exchangeClient = $exchangeClientBasic;
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}