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