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