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