Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.98% covered (success)
98.98%
97 / 98
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
ScopeAvailabilityDay
98.98% covered (success)
98.98%
97 / 98
83.33% covered (warning)
83.33%
5 / 6
18
0.00% covered (danger)
0.00%
0 / 1
 readResponse
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
2.00
 getScope
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getSlotBuckets
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
1 / 1
7
 getAvailabilityData
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
1 / 1
3
 readConflictList
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
 readAvailabilityList
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3/**
4 * @package Zmsadmin
5 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
6 **/
7
8namespace BO\Zmsadmin;
9
10use BO\Slim\Render;
11use BO\Zmsentities\Helper\DateTime;
12use BO\Zmsentities\Collection\AvailabilityList;
13use BO\Zmsentities\Collection\ProcessList;
14use BO\Zmsentities\Exception\UserAccountMissingRights;
15
16class ScopeAvailabilityDay extends BaseController
17{
18    /**
19     * @SuppressWarnings(Param)
20     * @return \Psr\Http\Message\ResponseInterface
21     */
22    #[\Override]
23    public function readResponse(
24        \Psr\Http\Message\RequestInterface $request,
25        \Psr\Http\Message\ResponseInterface $response,
26        array $args
27    ): \Psr\Http\Message\ResponseInterface {
28        $workstation = \App::$http->readGetResult('/workstation/', ['resolveReferences' => 1])->getEntity();
29        if (!$workstation->getUseraccount()->hasPermissions(['availability'])) {
30            throw new UserAccountMissingRights();
31        }
32        $data = static::getAvailabilityData(intval($args['id']), $args['date']);
33        $data['title'] = 'Behörden und Standorte - Öffnungszeiten';
34        $data['menuActive'] = 'owner';
35        $data['workstation'] = $workstation;
36        return Render::withHtml(
37            $response,
38            'page/availabilityday.twig',
39            $data
40        );
41    }
42
43    protected static function getScope($scopeId)
44    {
45        return \App::$http->readGetResult('/scope/' . $scopeId . '/', [
46            'resolveReferences' => 3
47        ])->getEntity();
48    }
49
50    protected static function getSlotBuckets($availabilityList, $processList)
51    {
52        $availability = $availabilityList->getFirst();
53
54        if (!$availability) {
55            return [];
56        }
57
58        $buckets = [];
59
60        $slotTimeInMinutes = $availability->getSlotTimeInMinutes();
61
62        foreach ($availabilityList->getSlotListByType('appointment') as $slot) {
63            $time = $slot->time;
64            $buckets[$time] = [
65                'time' => $time,
66                'timeString' => $slot->getTimeString(),
67                'public' => $slot->public,
68                'intern' => $slot->intern,
69                'occupiedCount' => 0,
70            ];
71        }
72
73        foreach ($processList as $process) {
74            $startTime = $process->getAppointments()->getFirst()->getStartTime()->format('H:i');
75            $endTime = $process->getAppointments()->getFirst()->getEndTimeWithCustomSlotTime($slotTimeInMinutes)->format('H:i');
76
77            $startDateTime = new \DateTime($startTime);
78            $endDateTime = new \DateTime($endTime);
79
80            foreach (array_keys($buckets) as $time) {
81                $slotDateTime = new \DateTime($time);
82                if ($slotDateTime >= $startDateTime && $slotDateTime < $endDateTime) {
83                    $buckets[$time]['occupiedCount']++;
84                }
85            }
86        }
87
88        uksort($buckets, function ($time1, $time2) {
89            return strtotime($time1) <=> strtotime($time2);
90        });
91
92        return $buckets;
93    }
94
95    protected static function getAvailabilityData($scopeId, $dateString)
96    {
97        $scope = static::getScope($scopeId);
98        $dateTime = new DateTime($dateString);
99        $dateWithTime = $dateTime->setTime(\App::$now->format('H'), \App::$now->format('i'));
100        $availabilityList = static::readAvailabilityList($scopeId, $dateWithTime);
101        $processList = \App::$http
102            ->readGetResult('/scope/' . $scopeId . '/process/' . $dateWithTime->format('Y-m-d') . '/')
103                ->getCollection()
104                ->toQueueList($dateWithTime)
105                ->withoutStatus(['fake'])
106                ->toProcessList();
107        if (!$processList->count()) {
108            $processList = new ProcessList();
109        }
110
111
112        $conflictList = static::readConflictList($scopeId, $dateWithTime);
113        $maxSlots = $availabilityList->getSummerizedSlotCount();
114        $busySlots = $availabilityList->getCalculatedSlotCount($processList);
115
116        return [
117            'slotBuckets' => static::getSlotBuckets($availabilityList, $processList),
118            'scope' => $scope,
119            'availabilityList' => $availabilityList->getArrayCopy(),
120            'conflicts' => ($conflictList) ? $conflictList
121                ->setConflictAmendment()
122                ->getArrayCopy() : [],
123            'processList' => $processList->getArrayCopy(),
124            'dateString' => $dateString,
125            'timestamp' => $dateWithTime->getTimestamp(),
126            'menuActive' => 'availability',
127            'maxWorkstationCount' => $availabilityList->getMaxWorkstationCount(),
128            'maxSlotsForAvailabilities' => $maxSlots,
129            'busySlotsForAvailabilities' => $busySlots,
130            'today' => \App::$now->getTimestamp()
131        ];
132    }
133
134    public static function readConflictList($scopeId, $dateTime)
135    {
136        $processConflictList = \App::$http
137            ->readGetResult('/scope/' . $scopeId . '/conflict/', [
138                'startDate' => $dateTime->format('Y-m-d'),
139                'endDate' => $dateTime->format('Y-m-d')
140            ])
141            ->getCollection();
142        return ($processConflictList) ? $processConflictList
143            ->sortByAppointmentDate()
144            ->withoutDublicatedConflicts()
145            ->toQueueList($dateTime)
146            ->withoutStatus(['fake', 'queued'])
147            ->toProcessList() : null;
148    }
149
150    public static function readAvailabilityList($scopeId, $dateTime)
151    {
152        try {
153            $availabilityList = \App::$http
154                ->readGetResult(
155                    '/scope/' . $scopeId . '/availability/',
156                    [
157                        'startDate' => $dateTime->format('Y-m-d'), //for skipping old availabilities
158                    ]
159                )
160                ->getCollection()->sortByCustomKey('startDate');
161        } catch (\BO\Zmsclient\Exception $exception) {
162            if ($exception->template != 'BO\Zmsapi\Exception\Availability\AvailabilityNotFound') {
163                throw $exception;
164            }
165            $availabilityList = new AvailabilityList();
166        }
167        return $availabilityList->withDateTime($dateTime); //withDateTime to check if opened
168    }
169}