Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.25% covered (warning)
86.25%
276 / 320
71.01% covered (warning)
71.01%
49 / 69
CRAP
0.00% covered (danger)
0.00%
0 / 1
Process
86.25% covered (warning)
86.25%
276 / 320
71.01% covered (warning)
71.01%
49 / 69
210.27
0.00% covered (danger)
0.00%
0 / 1
 getDefaults
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
1
 createFromScope
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 getRequests
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 getRequestIds
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRequestCSV
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addScope
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 addQueue
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 addRequests
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 updateRequests
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 hasScopeAdmin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 sendAdminMailOnConfirmation
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sendAdminMailOnDeleted
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sendAdminMailOnUpdated
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 shouldSendAdminMailOnClerkMail
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 withUpdatedData
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 addAppointmentFromRequest
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 addClientFromForm
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 setStatus
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getStatus
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getReminderTimestamp
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 addReminderTimestamp
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getAppointments
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 getClients
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
4.07
 hasAppointment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isWithAppointment
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 hasProcessCredentials
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
4
 withReassignedCredentials
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 hasQueueNumber
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 addAppointment
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getScopeId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCurrentScope
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAmendment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getShowUpTime
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 getWaitingTime
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getProcessingTime
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFinishTime
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addAmendment
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getCustomTextfield
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addCustomTextfield
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getCustomTextfield2
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addCustomTextfield2
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 addPriority
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
3
 getAuthKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPriority
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRandomAuthKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setCallTime
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getCallTimeString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCallTime
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getFirstClient
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getFirstAppointment
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 setStatusBySettings
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
5.03
 setClientsCount
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 withoutPersonalData
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 withLessData
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
20
 toCalendar
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 toQueue
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
5
 hasArrivalTime
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getArrivalTime
72.73% covered (warning)
72.73%
8 / 11
0.00% covered (danger)
0.00%
0 / 1
4.32
 setArrivalTime
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getWaitedSeconds
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWaitedMinutes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getWaySeconds
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getWayMinutes
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setWasMissed
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getWasMissed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 toDerefencedAmendment
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 toDerefencedCustomTextfield
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 toDerefencedCustomTextfield2
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 __toString
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3namespace BO\Zmsentities;
4
5use BO\Zmsentities\Helper\Property;
6
7/**
8 * @SuppressWarnings(Complexity)
9 * @SuppressWarnings(Coupling)
10 * @SuppressWarnings(Public)
11 *
12 */
13class Process extends Schema\Entity
14{
15    public const PRIMARY = 'id';
16    public const STATUS_FREE = 'free';
17    public const STATUS_RESERVED = 'reserved';
18    public const STATUS_CONFIRMED = 'confirmed';
19    public const STATUS_PRECONFIRMED = 'preconfirmed';
20    public const STATUS_QUEUED = 'queued';
21    public const STATUS_CALLED = 'called';
22    public const STATUS_PROCESSING = 'processing';
23    public const STATUS_PENDING = 'pending';
24    public const STATUS_PICKUP = 'pickup';
25    public const STATUS_FINISHED = 'finished';
26    public const STATUS_MISSED = 'missed';
27    public const STATUS_PARKED = 'parked';
28    public const STATUS_ARCHIVED = 'archived';
29    public const STATUS_DELETED = 'deleted';
30    public const STATUS_ANONYMIZED = 'anonymized';
31    public const STATUS_BLOCKED = 'blocked';
32    public const STATUS_CONFLICT = 'conflict';
33    public static $schema = "process.json";
34    public function getDefaults()
35    {
36        return [
37            'amendment' => '',
38            'customTextfield' => '',
39            'customTextfield2' => '',
40            'appointments' => new Collection\AppointmentList(),
41            'apiclient' => new Apiclient(),
42            'authKey' => '',
43            'captchaToken' => '',
44            'clients' => new Collection\ClientList(),
45            'createIP' => '',
46            'createTimestamp' => time(),
47            'id' => 0,
48            'archiveId' => 0,
49            'queue' => new Queue(),
50            'reminderTimestamp' => 0,
51            'requests' => new Collection\RequestList(),
52            'scope' => new Scope(),
53            'status' => 'free',
54            'dbstatus' => 'free',
55            'lastChange' => time(),
56            'wasMissed' => false,
57            'priority' => null,
58        ];
59    }
60
61    public static function createFromScope(Scope $scope, \DateTimeInterface $dateTime)
62    {
63        $appointment = new Appointment();
64        $appointment->addScope($scope->id);
65        $appointment->addSlotCount(0);
66        $appointment->addDate($dateTime->modify('00:00:00')->getTimestamp());
67        $process = new static();
68        $process->scope = $scope;
69        $process->setStatus('queued');
70        $process->addAppointment($appointment);
71        return $process;
72    }
73
74    /**
75     * @return Collection\RequestList
76     *
77     */
78    public function getRequests()
79    {
80        if (!$this->requests instanceof Collection\RequestList) {
81            $requestList = new Collection\RequestList();
82            foreach ($this->requests as $request) {
83                $request = ($request instanceof Request) ? $request : new Request($request);
84                $requestList->addEntity($request);
85            }
86            $this->requests = $requestList;
87        }
88        return $this->requests;
89    }
90
91    public function getRequestIds()
92    {
93        return $this->getRequests()->getIds();
94    }
95
96    public function getRequestCSV()
97    {
98        return $this->getRequests()->getIdsCsv();
99    }
100
101    public function addScope($scopeId)
102    {
103        $this->scope = new Scope(array('id' => $scopeId));
104        return $this;
105    }
106
107    public function addQueue($number, \DateTimeInterface $dateTime)
108    {
109        $this->queue = new Queue(array(
110            'number' => $number,
111            'arrivalTime' => $dateTime->getTimestamp(),
112            'priority' => $this->getPriority()
113        ));
114        return $this;
115    }
116
117    public function addRequests($source, $requestCSV)
118    {
119        $requestList = $this->getRequests();
120        foreach (explode(',', $requestCSV) as $id) {
121            if (!$requestList->hasRequests($id)) {
122                $this->requests[] = new Request(array(
123                    'source' => $source,
124                    'id' => $id
125                ));
126            }
127        }
128        return $this;
129    }
130
131    public function updateRequests($source, $requestCSV = '')
132    {
133        $this->requests = new Collection\RequestList();
134        if ($requestCSV) {
135            foreach (explode(',', $requestCSV) as $id) {
136                $this->requests->addEntity(new Request(array(
137                            'source' => $source,
138                            'id' => $id
139                        )));
140            }
141        }
142        return $this;
143    }
144
145    public function hasScopeAdmin()
146    {
147        return ('' != $this->toProperty()->scope->contact->email->get());
148    }
149
150    public function sendAdminMailOnConfirmation()
151    {
152        return (bool) ((int) $this->toProperty()->scope->preferences->client->adminMailOnAppointment->get());
153    }
154
155    public function sendAdminMailOnDeleted()
156    {
157        return (bool) ((int) $this->toProperty()->scope->preferences->client->adminMailOnDeleted->get());
158    }
159
160    public function sendAdminMailOnUpdated()
161    {
162        return (bool) ((int) $this->toProperty()->scope->preferences->client->adminMailOnUpdated->get());
163    }
164
165    public function shouldSendAdminMailOnClerkMail()
166    {
167        return (bool) ((int) $this->toProperty()->scope->preferences->client->adminMailOnMailSent->get());
168    }
169
170    public function withUpdatedData($requestData, \DateTimeInterface $dateTime, $scope = null, $notice = '')
171    {
172        $this->scope = ($scope) ? $scope : $this->scope;
173        $this->addAppointmentFromRequest($requestData, $dateTime);
174        $requestCsv = isset($requestData['requests']) ? implode(',', $requestData['requests']) : 0;
175        $this->updateRequests($scope->getSource(), $requestCsv);
176        $this->addClientFromForm($requestData);
177        $this->addReminderTimestamp($requestData, $dateTime);
178        $this->addAmendment($requestData, $notice);
179        $this->addCustomTextfield($requestData);
180        $this->addCustomTextfield2($requestData);
181        $this->addPriority($requestData);
182        return $this;
183    }
184
185    public function addAppointmentFromRequest($requestData, \DateTimeInterface $dateTime)
186    {
187        $this->appointments = null;
188        if (isset($requestData['selecteddate'])) {
189            $dateTime = new \DateTime($requestData['selecteddate']);
190        }
191        if (isset($requestData['selectedtime'])) {
192            $time = explode('-', $requestData['selectedtime']);
193            $dateTime->setTime($time[0], $time[1]);
194        }
195
196        $appointment = (new Appointment())
197            ->addDate($dateTime->getTimestamp())
198            ->addScope($this->scope['id']);
199        if (isset($requestData['slotCount'])) {
200            $appointment->addSlotCount($requestData['slotCount']);
201        }
202        $this->addAppointment($appointment);
203        return $this;
204    }
205
206    public function addClientFromForm($requestData)
207    {
208        $client = new Client();
209        foreach ($requestData as $key => $value) {
210            if (null !== $value && $client->offsetExists($key)) {
211                $client[$key] = (isset($value['value'])) ? $value['value'] : $value;
212            }
213        }
214        $this->clients = array();
215        $this->clients[] = $client;
216        return $this;
217    }
218
219    public function setStatus($status)
220    {
221        $this->status = $status;
222        return $this;
223    }
224
225    public function getStatus()
226    {
227        return $this->status;
228    }
229
230    public function getReminderTimestamp()
231    {
232        $timestamp = $this->toProperty()->reminderTimestamp->get();
233        return ($timestamp) ? $timestamp : 0;
234    }
235
236    public function addReminderTimestamp($input, \DateTimeInterface $dateTime)
237    {
238        $this->reminderTimestamp = (
239            Property::__keyExists('headsUpTime', $input) &&
240            $input['headsUpTime'] > 0
241        ) ? $dateTime->getTimestamp() - $input['headsUpTime'] : 0;
242        return $this;
243    }
244
245    /**
246     * @return \BO\Zmsentities\Collection\AppointmentList
247     *
248     */
249    public function getAppointments()
250    {
251        if (!$this['appointments'] instanceof Collection\AppointmentList) {
252            $this['appointments'] = new Collection\AppointmentList($this['appointments']);
253            foreach ($this['appointments'] as $index => $appointment) {
254                if (!$appointment instanceof Appointment) {
255                    $this['appointments'][$index] = new Appointment($appointment);
256                }
257            }
258        }
259        return $this['appointments'];
260    }
261
262    /**
263     * @return \BO\Zmsentities\Collection\ClientList
264     *
265     */
266    public function getClients()
267    {
268        if (!$this['clients'] instanceof Collection\ClientList) {
269            $this['clients'] = new Collection\ClientList($this['clients']);
270            foreach ($this['clients'] as $index => $client) {
271                if (!$client instanceof Client) {
272                    $this['clients'][$index] = new Client($client);
273                }
274            }
275        }
276        return $this['clients'];
277    }
278
279    public function hasAppointment($date, $scopeId)
280    {
281        return $this->getAppointments()->hasDateScope($date, $scopeId);
282    }
283
284    /**
285     * check if process is with appointment and not only queued
286     * return Boolean
287     */
288    public function isWithAppointment()
289    {
290        $appointment = $this->getFirstAppointment();
291        if ($appointment->hasTime()) {
292            return true;
293        }
294        return (1 == $this->toProperty()->queue->withAppointment->get());
295    }
296
297    public function hasProcessCredentials()
298    {
299        return (isset($this['id']) && isset($this['authKey']) && $this['id'] && $this['authKey']);
300    }
301
302    public function withReassignedCredentials($process)
303    {
304        $this->id = $process->getId();
305        $this->authKey = $process->getAuthKey();
306        return $this;
307    }
308
309    public function hasQueueNumber()
310    {
311        return (isset($this['queue']) && isset($this['queue']['number']) && $this['queue']['number']);
312    }
313
314    public function addAppointment(Appointment $newappointment)
315    {
316        $this->appointments[] = $newappointment;
317        return $this;
318    }
319
320    /**
321     * Reminder: A process might have multiple scopes. Each appointment can
322     * have his own scope. The scope in $this->scope is the current/next scope.
323     * This function returns the original scope ID and ignores internal scope
324     * which are used for processing like to pick up documents
325     *
326     */
327    public function getScopeId()
328    {
329        //TK 2020-09-28 changed because pickup and pending processes have assigned pickup scope
330        //as current scope - see zmsdb Query/Process EntityMapping
331        return $this->toProperty()->scope->id->get();
332    }
333
334    public function getCurrentScope(): Scope
335    {
336        return $this->getProperty('scope');
337    }
338
339    public function getAmendment()
340    {
341        return $this->toProperty()->amendment->get();
342    }
343
344    /*public function getShowUpTime()
345    {
346        return $this->toProperty()->showUpTime->get();
347    }*/
348
349    public function getShowUpTime($default = 'now', $timezone = null)
350    {
351        $showUpTime = $this->toProperty()->showUpTime->get();
352        $showDateTime = Helper\DateTime::create($default, $timezone);
353        if ($showUpTime) {
354            list($hours, $minutes, $seconds) = explode(':', $showUpTime);
355            $showDateTime = $showDateTime->setTime(intval($hours), intval($minutes), intval($seconds));
356        }
357        return $showDateTime;
358    }
359
360    public function getWaitingTime()
361    {
362        return $this->toProperty()->queue->waitingTime->get();
363    }
364
365    public function getProcessingTime()
366    {
367        return $this->toProperty()->processingTime->get();
368    }
369
370    public function getFinishTime()
371    {
372        return $this->toProperty()->finishTime->get();
373    }
374
375    public function addAmendment($input, $notice = '')
376    {
377        $this->amendment = $notice;
378        $this->amendment .= (isset($input['amendment']) && $input['amendment']) ? $input['amendment'] : '';
379        trim($this->amendment);
380        return $this;
381    }
382
383    public function getCustomTextfield()
384    {
385        return $this->toProperty()->customTextfield->get();
386    }
387
388    public function addCustomTextfield($input)
389    {
390        $this->customTextfield .= (
391            isset($input['customTextfield']) && $input['customTextfield']
392        ) ? $input['customTextfield'] : '';
393        trim($this->customTextfield);
394        return $this;
395    }
396
397    public function getCustomTextfield2()
398    {
399        return $this->toProperty()->customTextfield2->get();
400    }
401
402    public function addCustomTextfield2($input)
403    {
404        $this->customTextfield2 .= (
405            isset($input['customTextfield2']) && $input['customTextfield2']
406        ) ? $input['customTextfield2'] : '';
407        trim($this->customTextfield2);
408        return $this;
409    }
410
411    public function addPriority($input)
412    {
413        $this->priority = isset($input['priority']) && $input['priority'] ? $input['priority'] : null;
414
415        return $this;
416    }
417
418    public function getAuthKey()
419    {
420        return $this->toProperty()->authKey->get();
421    }
422
423    public function getPriority()
424    {
425        return (int) $this->toProperty()->priority->get();
426    }
427
428    public function setRandomAuthKey()
429    {
430        $this->authKey = substr(md5(rand()), 0, 4);
431    }
432
433    public function setCallTime($dateTime = null)
434    {
435        $this->queue['callTime'] = ($dateTime) ? $dateTime->getTimestamp() : 0;
436        return $this;
437    }
438
439    public function getCallTimeString()
440    {
441        return $this->getCallTime()->format('H:i:s');
442    }
443
444    public function getCallTime($default = 'now', $timezone = null)
445    {
446        $callTime = $this->toProperty()->queue->callTime->get();
447        $callDateTime = Helper\DateTime::create($default, $timezone);
448        if ($callTime) {
449            $callDateTime = $callDateTime->setTimestamp($callTime);
450        }
451        return $callDateTime;
452    }
453
454    public function getFirstClient()
455    {
456        $client = $this->getClients()->getFirst();
457        if (!$client) {
458            $client = new Client();
459            $this->clients->addEntity($client);
460        }
461        return $client;
462    }
463
464    public function getFirstAppointment(): Appointment
465    {
466        $appointment = $this->getAppointments()->getFirst();
467        if (!$appointment) {
468            $appointment = new Appointment();
469            $appointment->scope = $this->scope;
470            $this->appointments->addEntity($appointment);
471        }
472        return $appointment;
473    }
474
475    public function setStatusBySettings()
476    {
477        $scope = new Scope($this->scope);
478        if ('called' == $this->status && $this->queue['callCount'] > $scope->getPreference('queue', 'callCountMax')) {
479            $this->status = 'missed';
480        } elseif ('parked' == $this->status) {
481            $this->status = 'parked';
482        } elseif ('pickup' == $this->status) {
483            $this->status = 'queued';
484        } else {
485            $this->status = 'confirmed';
486        }
487        return $this;
488    }
489
490    public function setClientsCount($count)
491    {
492        $clientList = $this->getClients();
493        while ($clientList->count() < $count) {
494            $clientList->addEntity(new Client());
495        }
496        return $this;
497    }
498
499
500    public function withoutPersonalData()
501    {
502        $entity = clone $this;
503        if ($this->toProperty()->clients->isAvailable()) {
504            $client = $entity->getFirstClient();
505            unset($client['familyName']);
506            unset($client['email']);
507        }
508        return $entity;
509    }
510
511    /**
512     * Reduce data of dereferenced entities to a required minimum
513     *
514     */
515    public function withLessData(array $keepArray = [])
516    {
517        $entity = clone $this;
518        if (!in_array('availability', $keepArray)) {
519            foreach ($entity['appointments'] as $appointment) {
520                if ($appointment->toProperty()->scope->isAvailable()) {
521                    $scopeId = $appointment['scope']['id'];
522                    $appointment['scope'] = [
523                        'id' => $scopeId,
524                        'provider' => $appointment['scope']['provider'] ?? [],
525                        'shortName' => $appointment['scope']['shortName'] ?? ''
526                    ];
527                }
528                if ($appointment->toProperty()->availability->isAvailable()) {
529                    unset($appointment['availability']);
530                }
531            }
532        }
533
534        unset($entity['createTimestamp']);
535        unset($entity['createIP']);
536        if ($entity->toProperty()->scope->status->isAvailable()) {
537            unset($entity['scope']['status']);
538        }
539
540        if ($entity->status == 'free') {
541// delete keys
542            foreach (['authKey', 'queue', 'requests',] as $key) {
543                if (!in_array($key, $keepArray) && $entity->toProperty()->$key->isAvailable()) {
544                    unset($entity[$key]);
545                }
546            }
547            // delete if empty
548            foreach (['amendment', 'id', 'authKey', 'archiveId', 'reminderTimestamp',] as $key) {
549                if (!in_array($key, $keepArray) && $entity->toProperty()->$key->isAvailable() && !$entity[$key]) {
550                    unset($entity[$key]);
551                }
552            }
553            if (!in_array('provider', $keepArray) && $entity->toProperty()->scope->provider->data->isAvailable()) {
554                unset($entity['scope']['provider']['data']);
555            }
556        }
557
558        if (!in_array('dayoff', $keepArray) && $entity->toProperty()->scope->dayoff->isAvailable()) {
559            unset($entity['scope']['dayoff']);
560        }
561        if (!in_array('scope', $keepArray) && $entity->toProperty()->scope->preferences->isAvailable()) {
562            unset($entity['scope']['preferences']);
563        }
564        return $entity;
565    }
566
567    public function toCalendar()
568    {
569        $calendar = new Calendar();
570        $dateTime = $this->getFirstAppointment()->toDateTime();
571        $day = new Day();
572        $day->setDateTime($dateTime);
573        $calendar->firstDay = $day;
574        $calendar->lastDay = $day;
575        $calendar->requests = clone $this->getRequests();
576        $calendar->scopes = new Collection\ScopeList([$this->scope]);
577        return $calendar;
578    }
579
580    public function toQueue(\DateTimeInterface $dateTime)
581    {
582        $queue = new Queue($this->queue);
583        $queue->withAppointment = ($this->getFirstAppointment()->hasTime()) ? true : false;
584        $queue->waitingTime = ($queue->waitingTime) ? $queue->waitingTime : 0;
585        $queue->wayTime = ($queue->wayTime) ? $queue->wayTime : 0;
586        if ($queue->withAppointment) {
587            $queue->number = $this->id;
588        } else {
589            $queue->number = $this->toProperty()->queue->number->get();
590        }
591        $queue->arrivalTime = $this->getArrivalTime($dateTime)->getTimestamp();
592        $queue->priority = $this->priority;
593        return $queue->setProcess($this);
594    }
595
596    public function hasArrivalTime()
597    {
598        $arrivalTime = 0;
599        if ($this->isWithAppointment()) {
600            $arrivalTime = $this->getFirstAppointment()->date;
601        } else {
602            $arrivalTime = $this->toProperty()->queue->arrivalTime->get();
603        }
604        return ($arrivalTime) ? true : false;
605    }
606
607    public function getArrivalTime($default = 'now', $timezone = null)
608    {
609        $queueArrivalTime = $this->toProperty()->queue->arrivalTime->get();
610
611        if ($queueArrivalTime) {
612            // Falls der Queue-Wert vorhanden ist – auch wenn ein Termin existiert – verwende diesen (dabei ist handelt es sich, um verpasste Termine)
613            $arrivalTime = $queueArrivalTime;
614        } elseif ($this->isWithAppointment()) {
615            $arrivalTime = $this->getFirstAppointment()->date;
616        } else {
617            $arrivalTime = 0;
618        }
619
620        $arrivalTime = (int)$arrivalTime;
621        $arrivalDateTime = Helper\DateTime::create($default, $timezone);
622        if ($arrivalTime) {
623            $arrivalDateTime = $arrivalDateTime->setTimestamp($arrivalTime);
624        }
625        return $arrivalDateTime;
626    }
627
628    public function setArrivalTime(\DateTimeInterface $dateTime = null)
629    {
630        $this->queue['arrivalTime'] = ($dateTime) ? $dateTime->getTimestamp() : 0;
631        return $this;
632    }
633
634    /**
635     * Calculate real waiting time, only available after called
636     */
637    public function getWaitedSeconds($defaultTime = 'now')
638    {
639        return $this->getCallTime($defaultTime)->getTimestamp() - $this->getArrivalTime($defaultTime)->getTimestamp();
640    }
641
642    public function getWaitedMinutes($defaultTime = 'now')
643    {
644        return $this->getWaitedSeconds($defaultTime) / 60;
645    }
646
647    public function getWaySeconds($defaultTime = 'now')
648    {
649        return $this->getShowUpTime($defaultTime)->getTimestamp() - $this->getCallTime($defaultTime)->getTimestamp();
650    }
651
652    public function getWayMinutes($defaultTime = 'now')
653    {
654        return $this->getWaySeconds($defaultTime) / 60;
655    }
656
657    public function setWasMissed(bool $bool)
658    {
659        $this->wasMissed = $bool;
660        $this->status = self::STATUS_MISSED;
661        return $this;
662    }
663
664    public function getWasMissed(): bool
665    {
666        return (bool) $this->wasMissed;
667    }
668
669    public function toDerefencedAmendment()
670    {
671        $lastChange = (new \DateTimeImmutable())->setTimestamp($this->createTimestamp)->format('c');
672        return var_export(array(
673                'BuergerID' => $this->id,
674                'StandortID' => $this->scope['id'],
675                'Anmerkung' => null,
676                'IPTimeStamp' => $this->createTimestamp,
677                'LastChange' => $lastChange,
678            ), 1);
679    }
680
681    public function toDerefencedCustomTextfield()
682    {
683        $lastChange = (new \DateTimeImmutable())->setTimestamp($this->createTimestamp)->format('c');
684        return var_export(array(
685                'BuergerID' => $this->id,
686                'StandortID' => $this->scope['id'],
687                'CustomTextfield' => null,
688                'IPTimeStamp' => $this->createTimestamp,
689                'LastChange' => $lastChange,
690            ), 1);
691    }
692
693    public function toDerefencedCustomTextfield2()
694    {
695        $lastChange = (new \DateTimeImmutable())->setTimestamp($this->createTimestamp)->format('c');
696        return var_export(array(
697                'BuergerID' => $this->id,
698                'StandortID' => $this->scope['id'],
699                'CustomTextfield2' => null,
700                'IPTimeStamp' => $this->createTimestamp,
701                'LastChange' => $lastChange,
702            ), 1);
703    }
704
705    public function __toString()
706    {
707        $string = "process#";
708        $string .= $this->id ?: $this->archiveId;
709        $string .= ":" . $this->authKey;
710        $string .= " (" . $this->status . ")";
711        $string .= " " . $this->getFirstAppointment()->toDateTime()->format('c');
712        $string .= " " . ($this->isWithAppointment() ? "appoint" : "arrival:" . $this->getArrivalTime()->format('c'));
713        $string .= " " . $this->getFirstAppointment()->slotCount . "slots";
714        $string .= "*" . count($this->appointments);
715        foreach ($this->getRequests() as $request) {
716            $string .= " " . $request['source'] . "." . $request['id'];
717        }
718        $string .= " scope." . $this['scope']['id'];
719        $string .= " ~" . base_convert($this['lastChange'], 10, 35);
720        $string .= " client:" . $this['apiclient']['shortname'];
721        $string .= " token:" . ($this['captchaToken'] ?? '(none)');
722        return $string;
723    }
724}