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