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