Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
96.77% |
180 / 186 |
|
70.59% |
12 / 17 |
CRAP | |
0.00% |
0 / 1 |
ZmsApiClientService | |
96.77% |
180 / 186 |
|
70.59% |
12 / 17 |
65 | |
0.00% |
0 / 1 |
fetchSourceData | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
5 | |||
getOffices | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
3.03 | |||
getScopes | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
3.03 | |||
getServices | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
3.03 | |||
getRequestRelationList | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
3.03 | |||
getFreeDays | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
6 | |||
getFreeTimeslots | |
100.00% |
23 / 23 |
|
100.00% |
1 / 1 |
8 | |||
reserveTimeslot | |
100.00% |
26 / 26 |
|
100.00% |
1 / 1 |
6 | |||
submitClientData | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
preconfirmProcess | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
confirmProcess | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
cancelAppointment | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
sendConfirmationEmail | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
sendPreconfirmationEmail | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
sendCancellationEmail | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
getProcessById | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
3 | |||
getScopesByProviderId | |
77.78% |
7 / 9 |
|
0.00% |
0 / 1 |
4.18 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace BO\Zmscitizenapi\Services\Core; |
6 | |
7 | use BO\Zmscitizenapi\Helper\ClientIpHelper; |
8 | use BO\Zmscitizenapi\Services\Core\LoggerService; |
9 | use BO\Zmscitizenapi\Services\Core\ExceptionService; |
10 | use BO\Zmsentities\Calendar; |
11 | use BO\Zmsentities\Process; |
12 | use BO\Zmsentities\Source; |
13 | use BO\Zmsentities\Collection\DayList; |
14 | use BO\Zmsentities\Collection\ProcessList; |
15 | use BO\Zmsentities\Collection\ProviderList; |
16 | use BO\Zmsentities\Collection\RequestList; |
17 | use BO\Zmsentities\Collection\RequestRelationList; |
18 | use BO\Zmsentities\Collection\ScopeList; |
19 | |
20 | class ZmsApiClientService |
21 | { |
22 | private static function fetchSourceData(): Source |
23 | { |
24 | $cacheKey = 'source_' . \App::$source_name; |
25 | if (\App::$cache && ($data = \App::$cache->get($cacheKey))) { |
26 | return $data; |
27 | } |
28 | |
29 | $result = \App::$http->readGetResult('/source/' . \App::$source_name . '/', [ |
30 | 'resolveReferences' => 2, |
31 | ]); |
32 | $entity = $result?->getEntity(); |
33 | if (!$entity instanceof Source) { |
34 | return new Source(); |
35 | } |
36 | |
37 | if (\App::$cache) { |
38 | \App::$cache->set($cacheKey, $entity, \App::$SOURCE_CACHE_TTL); |
39 | LoggerService::logInfo('Cache set', [ |
40 | 'key' => $cacheKey, |
41 | 'ttl' => \App::$SOURCE_CACHE_TTL, |
42 | 'entity_type' => get_class($entity) |
43 | ]); |
44 | } |
45 | |
46 | return $entity; |
47 | } |
48 | |
49 | public static function getOffices(): ProviderList |
50 | { |
51 | try { |
52 | $sources = self::fetchSourceData(); |
53 | $list = $sources?->getProviderList(); |
54 | if (!$list instanceof ProviderList) { |
55 | return new ProviderList(); |
56 | } |
57 | return $list; |
58 | } catch (\Exception $e) { |
59 | ExceptionService::handleException($e); |
60 | } |
61 | } |
62 | |
63 | public static function getScopes(): ScopeList |
64 | { |
65 | try { |
66 | $sources = self::fetchSourceData(); |
67 | $list = $sources?->getScopeList(); |
68 | if (!$list instanceof ScopeList) { |
69 | return new ScopeList(); |
70 | } |
71 | return $list; |
72 | } catch (\Exception $e) { |
73 | ExceptionService::handleException($e); |
74 | } |
75 | } |
76 | |
77 | public static function getServices(): RequestList |
78 | { |
79 | try { |
80 | $sources = self::fetchSourceData(); |
81 | $list = $sources?->getRequestList(); |
82 | if (!$list instanceof RequestList) { |
83 | return new RequestList(); |
84 | } |
85 | return $list; |
86 | } catch (\Exception $e) { |
87 | ExceptionService::handleException($e); |
88 | } |
89 | } |
90 | |
91 | public static function getRequestRelationList(): RequestRelationList |
92 | { |
93 | try { |
94 | $sources = self::fetchSourceData(); |
95 | $list = $sources?->getRequestRelationList(); |
96 | if (!$list instanceof RequestRelationList) { |
97 | return new RequestRelationList(); |
98 | } |
99 | return $list; |
100 | } catch (\Exception $e) { |
101 | ExceptionService::handleException($e); |
102 | } |
103 | } |
104 | |
105 | public static function getFreeDays(ProviderList $providers, RequestList $requests, array $firstDay, array $lastDay): Calendar |
106 | { |
107 | try { |
108 | $calendar = new Calendar(); |
109 | $calendar->firstDay = $firstDay; |
110 | $calendar->lastDay = $lastDay; |
111 | $calendar->providers = $providers; |
112 | $calendar->requests = $requests; |
113 | $result = \App::$http->readPostResult('/calendar/', $calendar); |
114 | $entity = $result?->getEntity(); |
115 | |
116 | if (!$entity instanceof Calendar) { |
117 | return new Calendar(); |
118 | } |
119 | $bookableDays = new DayList(); |
120 | foreach ($entity->days as $day) { |
121 | if (isset($day['status']) && $day['status'] === 'bookable') { |
122 | $bookableDays->addEntity($day); |
123 | } |
124 | } |
125 | $entity->days = $bookableDays; |
126 | |
127 | return $entity; |
128 | } catch (\Exception $e) { |
129 | ExceptionService::handleException($e); |
130 | } |
131 | } |
132 | |
133 | public static function getFreeTimeslots(ProviderList $providers, RequestList $requests, array $firstDay, array $lastDay): ProcessList |
134 | { |
135 | try { |
136 | $calendar = new Calendar(); |
137 | $calendar->firstDay = $firstDay; |
138 | $calendar->lastDay = $lastDay; |
139 | $calendar->providers = $providers; |
140 | $calendar->requests = $requests; |
141 | $result = \App::$http->readPostResult('/process/status/free/', $calendar); |
142 | $collection = $result?->getCollection(); |
143 | if (!$collection instanceof ProcessList) { |
144 | return new ProcessList(); |
145 | } |
146 | |
147 | $uniqueProcesses = new ProcessList(); |
148 | $seenKeys = []; |
149 | foreach ($collection as $process) { |
150 | $appointment = $process->appointments->getFirst(); |
151 | $providerId = isset($process->scope->provider->id) ? $process->scope->provider->id : null; |
152 | if ($appointment && $providerId) { |
153 | $key = $providerId . '_' . $appointment->date; |
154 | if (!isset($seenKeys[$key])) { |
155 | $uniqueProcesses->addEntity($process); |
156 | $seenKeys[$key] = true; |
157 | } |
158 | } else { |
159 | $uniqueProcesses->addEntity($process); |
160 | } |
161 | } |
162 | |
163 | return $uniqueProcesses; |
164 | } catch (\Exception $e) { |
165 | ExceptionService::handleException($e); |
166 | } |
167 | } |
168 | |
169 | public static function reserveTimeslot(Process $appointmentProcess, array $serviceIds, array $serviceCounts): Process |
170 | { |
171 | try { |
172 | $requests = []; |
173 | foreach ($serviceIds as $index => $serviceId) { |
174 | $count = intval($serviceCounts[$index]); |
175 | for ($i = 0; $i < $count; $i++) { |
176 | $requests[] = [ |
177 | 'id' => $serviceId, |
178 | 'source' => \App::$source_name |
179 | ]; |
180 | } |
181 | } |
182 | |
183 | $processEntity = new Process(); |
184 | $processEntity->appointments = $appointmentProcess->appointments ?? []; |
185 | $processEntity->authKey = $appointmentProcess->authKey ?? null; |
186 | $processEntity->clients = $appointmentProcess->clients ?? []; |
187 | $processEntity->scope = $appointmentProcess->scope ?? null; |
188 | $processEntity->requests = $requests; |
189 | $processEntity->lastChange = $appointmentProcess->lastChange ?? time(); |
190 | $processEntity->createIP = ClientIpHelper::getClientIp(); |
191 | $processEntity->createTimestamp = time(); |
192 | if (isset($appointmentProcess->queue)) { |
193 | $processEntity->queue = $appointmentProcess->queue; |
194 | } |
195 | |
196 | $result = \App::$http->readPostResult('/process/status/reserved/', $processEntity); |
197 | $entity = $result?->getEntity(); |
198 | if (!$entity instanceof Process) { |
199 | return new Process(); |
200 | } |
201 | return $entity; |
202 | } catch (\Exception $e) { |
203 | ExceptionService::handleException($e); |
204 | } |
205 | } |
206 | |
207 | public static function submitClientData(Process $process): Process |
208 | { |
209 | try { |
210 | $url = "/process/{$process->id}/{$process->authKey}/"; |
211 | $result = \App::$http->readPostResult($url, $process); |
212 | $entity = $result?->getEntity(); |
213 | if (!$entity instanceof Process) { |
214 | return new Process(); |
215 | } |
216 | return $entity; |
217 | } catch (\Exception $e) { |
218 | ExceptionService::handleException($e); |
219 | } |
220 | } |
221 | |
222 | public static function preconfirmProcess(Process $process): Process |
223 | { |
224 | try { |
225 | $url = '/process/status/preconfirmed/'; |
226 | $result = \App::$http->readPostResult($url, $process); |
227 | $entity = $result?->getEntity(); |
228 | if (!$entity instanceof Process) { |
229 | return new Process(); |
230 | } |
231 | return $entity; |
232 | } catch (\Exception $e) { |
233 | ExceptionService::handleException($e); |
234 | } |
235 | } |
236 | |
237 | public static function confirmProcess(Process $process): Process |
238 | { |
239 | try { |
240 | $url = '/process/status/confirmed/'; |
241 | $result = \App::$http->readPostResult($url, $process); |
242 | $entity = $result?->getEntity(); |
243 | if (!$entity instanceof Process) { |
244 | return new Process(); |
245 | } |
246 | return $entity; |
247 | } catch (\Exception $e) { |
248 | ExceptionService::handleException($e); |
249 | } |
250 | } |
251 | |
252 | public static function cancelAppointment(Process $process): Process |
253 | { |
254 | try { |
255 | $url = "/process/{$process->id}/{$process->authKey}/"; |
256 | $result = \App::$http->readDeleteResult($url, []); |
257 | $entity = $result?->getEntity(); |
258 | if (!$entity instanceof Process) { |
259 | return new Process(); |
260 | } |
261 | return $entity; |
262 | } catch (\Exception $e) { |
263 | ExceptionService::handleException($e); |
264 | } |
265 | } |
266 | |
267 | public static function sendConfirmationEmail(Process $process): Process |
268 | { |
269 | try { |
270 | $url = "/process/{$process->id}/{$process->authKey}/confirmation/mail/"; |
271 | $result = \App::$http->readPostResult($url, $process); |
272 | $entity = $result?->getEntity(); |
273 | if (!$entity instanceof Process) { |
274 | return new Process(); |
275 | } |
276 | return $entity; |
277 | } catch (\Exception $e) { |
278 | ExceptionService::handleException($e); |
279 | } |
280 | } |
281 | |
282 | public static function sendPreconfirmationEmail(Process $process): Process |
283 | { |
284 | try { |
285 | $url = "/process/{$process->id}/{$process->authKey}/preconfirmation/mail/"; |
286 | $result = \App::$http->readPostResult($url, $process); |
287 | $entity = $result?->getEntity(); |
288 | if (!$entity instanceof Process) { |
289 | return new Process(); |
290 | } |
291 | return $entity; |
292 | } catch (\Exception $e) { |
293 | ExceptionService::handleException($e); |
294 | } |
295 | } |
296 | |
297 | public static function sendCancellationEmail(Process $process): Process |
298 | { |
299 | try { |
300 | $url = "/process/{$process->id}/{$process->authKey}/delete/mail/"; |
301 | $result = \App::$http->readPostResult($url, $process); |
302 | $entity = $result?->getEntity(); |
303 | if (!$entity instanceof Process) { |
304 | return new Process(); |
305 | } |
306 | return $entity; |
307 | } catch (\Exception $e) { |
308 | ExceptionService::handleException($e); |
309 | } |
310 | } |
311 | |
312 | public static function getProcessById(int $processId, string $authKey): Process |
313 | { |
314 | try { |
315 | $resolveReferences = 2; |
316 | $result = \App::$http->readGetResult("/process/{$processId}/{$authKey}/", [ |
317 | 'resolveReferences' => $resolveReferences |
318 | ]); |
319 | $entity = $result?->getEntity(); |
320 | if (!$entity instanceof Process) { |
321 | return new Process(); |
322 | } |
323 | return $entity; |
324 | } catch (\Exception $e) { |
325 | ExceptionService::handleException($e); |
326 | } |
327 | } |
328 | |
329 | public static function getScopesByProviderId(string $source, string|int $providerId): ScopeList |
330 | { |
331 | try { |
332 | $scopeList = self::getScopes(); |
333 | if (!$scopeList instanceof ScopeList) { |
334 | return new ScopeList(); |
335 | } |
336 | $result = $scopeList->withProviderID($source, (string) $providerId); |
337 | if (!$result instanceof ScopeList) { |
338 | return new ScopeList(); |
339 | } |
340 | return $result; |
341 | } catch (\Exception $e) { |
342 | ExceptionService::handleException($e); |
343 | } |
344 | } |
345 | } |