Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.24% covered (success)
98.24%
167 / 170
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ExchangeWaitingscope
98.24% covered (success)
98.24%
167 / 170
57.14% covered (warning)
57.14%
4 / 7
20
0.00% covered (danger)
0.00%
0 / 1
 readEntity
100.00% covered (success)
100.00%
42 / 42
100.00% covered (success)
100.00%
1 / 1
3
 readSubjectList
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 readPeriodList
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
4
 readByDateTime
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
2
 writeWaitingTimeCalculated
95.24% covered (success)
95.24%
20 / 21
0.00% covered (danger)
0.00%
0 / 1
3
 writeWaitingTime
96.30% covered (success)
96.30%
26 / 27
0.00% covered (danger)
0.00%
0 / 1
4
 updateWaitingStatistics
96.43% covered (success)
96.43%
27 / 28
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace BO\Zmsdb;
4
5use BO\Zmsentities\Exchange;
6
7class ExchangeWaitingscope extends Base implements Interfaces\ExchangeSubject
8{
9    #[\Override]
10    public function readEntity(
11        $subjectid,
12        \DateTimeInterface $datestart,
13        \DateTimeInterface $dateend,
14        $period = 'day'
15    ) {
16        $scope = (new Scope())->readEntity($subjectid);
17        $entity = new Exchange();
18        $entity['title'] = "Wartestatistik " . $scope->contact->name . " " . $scope->shortName;
19        $entity->setPeriod($datestart, $dateend, $period);
20        $entity->addDictionaryEntry('subjectid', 'string', 'ID of a scope', 'scope.id');
21        $entity->addDictionaryEntry('date', 'string', 'date of report entry');
22        $entity->addDictionaryEntry('hour', 'string', 'hour of report entry');
23        $entity->addDictionaryEntry('waitingcount', 'number', 'amount of waiting spontaneous clients');
24        $entity->addDictionaryEntry('waitingtime', 'number', 'real waitingtime for spontaneous clients');
25        $entity->addDictionaryEntry('waytime', 'number', 'real waytime for spontaneous clients');
26        $entity->addDictionaryEntry('waitingcalculated', 'number', 'calculated waitingtime for spontaneous clients');
27        $entity->addDictionaryEntry('waitingcount_termin', 'number', 'amount of waiting clients with termin');
28        $entity->addDictionaryEntry('waitingtime_termin', 'number', 'real waitingtime with termin');
29        $entity->addDictionaryEntry('waytime_termin', 'number', 'real waytime with appointment');
30        $entity->addDictionaryEntry('waitingcalculated_termin', 'number', 'calculated waitingtime with termin');
31        $subjectIdList = explode(',', $subjectid);
32
33        $raw = $this
34            ->getReader()
35            ->fetchAll(
36                constant("\BO\Zmsdb\Query\ExchangeWaitingscope::QUERY_READ_" . strtoupper($period)),
37                [
38                    'scopeid' => $subjectIdList,
39                    'datestart' => $datestart->format('Y-m-d'),
40                    'dateend' => $dateend->format('Y-m-d')
41                ]
42            );
43
44        foreach ($raw as $entry) {
45            foreach (range(7, 19) as $hour) {
46                $entity->addDataSet([
47                    $entry['standortid'],
48                    $entry['datum'],
49                    $hour,
50                    $entry[sprintf('hour_%02d_waiting_count_spontaneous', $hour)],
51                    $entry[sprintf('hour_%02d_waiting_time_spontaneous', $hour)],
52                    $entry[sprintf('hour_%02d_way_time_spontaneous', $hour)],
53                    $entry[sprintf('hour_%02d_estimated_waiting_time_spontaneous', $hour)],
54                    $entry[sprintf('hour_%02d_waiting_count_appointment', $hour)],
55                    $entry[sprintf('hour_%02d_waiting_time_appointment', $hour)],
56                    $entry[sprintf('hour_%02d_way_time_appointment', $hour)],
57                    $entry[sprintf('hour_%02d_estimated_waiting_time_appointment', $hour)],
58                ]);
59            }
60        }
61
62        return $entity;
63    }
64
65    #[\Override]
66    public function readSubjectList()
67    {
68        $raw = $this->getReader()->fetchAll(Query\ExchangeWaitingscope::QUERY_SUBJECTS, []);
69        $entity = new Exchange();
70        $entity['title'] = "Wartestatistik";
71        $entity->setPeriod(new \DateTimeImmutable(), new \DateTimeImmutable());
72        $entity->addDictionaryEntry('subject', 'string', 'Standort ID', 'scope.id');
73        $entity->addDictionaryEntry('periodstart', 'string', 'Datum von');
74        $entity->addDictionaryEntry('periodend', 'string', 'Datum bis');
75        $entity->addDictionaryEntry('description', 'string', 'Standort Beschreibung');
76        foreach ($raw as $entry) {
77            $entity->addDataSet(array_values($entry));
78        }
79        return $entity;
80    }
81
82    #[\Override]
83    public function readPeriodList($subjectid, $period = 'day')
84    {
85        $scope = (new Scope())->readEntity($subjectid);
86        $entity = new Exchange();
87        $entity['title'] = "Wartestatistik " . $scope->contact->name . " " . $scope->shortName;
88        $entity->setPeriod(new \DateTimeImmutable(), new \DateTimeImmutable(), $period);
89        $entity->addDictionaryEntry('period');
90
91        $montsList = $this->getReader()->fetchAll(
92            constant("\BO\Zmsdb\Query\ExchangeWaitingscope::QUERY_PERIODLIST_MONTH"),
93            [
94                'scopeid' => $subjectid,
95            ]
96        );
97        $raw = [];
98        foreach ($montsList as $month) {
99            $date = new \DateTimeImmutable($month['date']);
100            $raw[$date->format('Y')][] = $month['date'];
101            rsort($raw[$date->format('Y')]);
102        }
103        krsort($raw);
104
105        foreach ($raw as $year => $months) {
106            $entity->addDataSet([$year]);
107            foreach ($months as $month) {
108                $entity->addDataSet([$month]);
109            }
110        }
111        return $entity;
112    }
113
114    /**
115     * fetch entry by scope and date or create an entry, if it does not exists
116     * the returned entry is save for updating
117     */
118    public function readByDateTime(
119        \BO\Zmsentities\Scope $scope,
120        \DateTimeInterface $date,
121        bool $isWithAppointment = false
122    ) {
123        $sql = Query\ExchangeWaitingscope::getQuerySelectByDateTime($date, $isWithAppointment);
124        $existingEntry = $this->getReader()->fetchOne(
125            $sql,
126            [
127                'scopeid' => $scope->id,
128                'date' => $date->format('Y-m-d'),
129                'hour' => $date->format('H')
130            ]
131        );
132        if (!$existingEntry) {
133            $this->perform(
134                Query\ExchangeWaitingscope::QUERY_CREATE,
135                [
136                    'scopeid' => $scope->id,
137                    'date' => $date->format('Y-m-d'),
138                ]
139            );
140            $existingEntry = $this->readByDateTime($scope, $date, $isWithAppointment);
141        }
142        return $existingEntry;
143    }
144
145    /**
146     * Write calculated waiting time and count of queued processes into statistic
147     */
148    public function writeWaitingTimeCalculated(
149        \BO\Zmsentities\Scope $scope,
150        \DateTimeInterface $now,
151        bool $isWithAppointment = false
152    ) {
153        if ($now > (new \DateTime())) {
154            return $this;
155        }
156
157        $queueList = (new Scope())->readQueueListWithWaitingTime($scope, $now);
158
159        $existingEntry = $this->readByDateTime($scope, $now, $isWithAppointment);
160        $queueEntry = $queueList->getFakeOrLastWaitingnumber();
161        $waitingCalculated = $existingEntry['waitingcalculated'] > $queueEntry['waitingTimeEstimate'] ?
162            $existingEntry['waitingcalculated']
163            : $queueEntry['waitingTimeEstimate'];
164
165        $this->perform(
166            Query\ExchangeWaitingscope::getQueryUpdateByDateTime($now, $isWithAppointment),
167            [
168                'waitingcalculated' => $waitingCalculated,
169                'waitingcount' => $existingEntry['waitingcount'],
170                'waitingtime' => $existingEntry['waitingtime'],
171                'waytime' => $existingEntry['waytime'],
172                'scopeid' => $scope->id,
173                'date' => $now->format('Y-m-d'),
174                'hour' => $now->format('H')
175            ]
176        );
177        return $this;
178    }
179
180    /**
181     * Write real waiting time into statistics
182     */
183    public function writeWaitingTime(
184        \BO\Zmsentities\Process $process,
185        \DateTimeInterface $now
186    ) {
187        if ($now > (new \DateTime())) {
188            return $this;
189        }
190
191        $waitingTime = $process->getWaitedMinutes($now);
192        $wayTime = $process->getWayMinutes($now);
193        $existingEntry = $this->readByDateTime(
194            $process->scope,
195            $process->getArrivalTime($now),
196            $process->isWithAppointment()
197        );
198        $waitingTime = $existingEntry['waitingtime'] > $waitingTime ? $existingEntry['waitingtime'] : $waitingTime;
199        $wayTime = $existingEntry['waytime'] > $wayTime ? $existingEntry['waytime'] : $wayTime;
200        $this->perform(
201            Query\ExchangeWaitingscope::getQueryUpdateByDateTime(
202                $process->getArrivalTime($now),
203                $process->isWithAppointment()
204            ),
205            [
206                'waitingcalculated' => $existingEntry['waitingcalculated'],
207                'waitingcount' => $existingEntry['waitingcount'],
208                'waitingtime' => $waitingTime,
209                'waytime' => $wayTime,
210                'scopeid' => $process->scope->id,
211                'date' => $now->format('Y-m-d'),
212                'hour' => $now->format('H')
213            ]
214        );
215        return $this;
216    }
217
218    public function updateWaitingStatistics(
219        \BO\Zmsentities\Process $process,
220        \DateTimeInterface $now
221    ) {
222        if ($now > (new \DateTime())) {
223            return $this;
224        }
225
226        $newWaitingTime = $process->getWaitedMinutes($now);
227        $newWayTime = $process->getWayMinutes($now);
228
229        $existingEntry = $this->readByDateTime(
230            $process->scope,
231            $process->getArrivalTime($now),
232            $process->isWithAppointment()
233        );
234
235        $waitingCount = $existingEntry['waitingcount'] + 1;
236
237        $averageWaitingTime = ($existingEntry['waitingtime'] * $existingEntry['waitingcount'] + $newWaitingTime) / $waitingCount;
238        $averageWayTime = ($existingEntry['waytime'] * $existingEntry['waitingcount'] + $newWayTime) / $waitingCount;
239
240        $this->perform(
241            Query\ExchangeWaitingscope::getQueryUpdateByDateTime(
242                $process->getArrivalTime($now),
243                $process->isWithAppointment()
244            ),
245            [
246                'waitingcalculated' => $existingEntry['waitingcalculated'],
247                'waitingcount' => $waitingCount,
248                'waitingtime' => $averageWaitingTime,
249                'waytime' => $averageWayTime,
250                'scopeid' => $process->scope->id,
251                'date' => $now->format('Y-m-d'),
252                'hour' => $now->format('H')
253            ]
254        );
255
256        return $this;
257    }
258}