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