blob: 87b5ed65623f28934e99a6cd24553b6606a7cc65 [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001<?php
2class schedules {
3 const STATUS_NO_ACTIVE_SCHEDULE = 0;
4 const STATUS_HALFWAY_CONFIGURED_SCHEDULE = 1;
5 const STATUS_ACTIVE_SCHEDULE = 2;
6
7 public static $allEvents = ["work", "breakfast", "lunch"];
8 public static $otherEvents = ["breakfast", "lunch"];
9 public static $otherEventsDescription = [
10 "breakfast" => "Desayuno",
11 "lunch" => "Comida"
12 ];
13 public static $workerScheduleStatus = [
14 0 => "No hay ningún calendario activo",
15 1 => "Hay un calendario activo pero no está completamente configurado",
16 2 => "Hay un calendario activo completamente configurado"
17 ];
18 public static $workerScheduleStatusShort = [
19 0 => "No hay un horario activo",
20 1 => "No está configurado del todo",
21 2 => "Existe uno configurado"
22 ];
23 public static $workerScheduleStatusColors = [
24 0 => "red",
25 1 => "orange",
26 2 => "green"
27 ];
28
29 public static function time2sec($time) {
30 $e = explode(":", $time);
31 return ((int)$e[0]*60 + (int)$e[1])*60;
32 }
33
34 public static function sec2time($sec, $autoShowSeconds = true) {
35 $min = floor($sec/60);
36 $secr = $sec % 60;
37 return visual::padNum(floor($min/60), 2).":".visual::padNum(($min % 60), 2).($autoShowSeconds && $secr != 0 ? ":".visual::padNum($secr, 2) : "");
38 }
39
40 // TEMPLATES:
41
42 public static function addTemplate($name, $ibegins, $iends) {
43 global $con;
44
45 $sname = db::sanitize($name);
46 $begins = new DateTime($ibegins);
47 $sbegins = (int)$begins->getTimestamp();
48 $ends = new DateTime($iends);
49 $sends = (int)$ends->getTimestamp();
50
51 if (!intervals::wellFormed([$sbegins, $sends])) return 2;
52
53 return (mysqli_query($con, "INSERT INTO scheduletemplates (name, begins, ends) VALUES ('$sname', $sbegins, $sends)") ? 0 : 1);
54 }
55
56 private static function _addDaysToReturn(&$return, $stableDays, $sfieldSchedule, $sid) {
57 global $con;
58
59 $return["days"] = [];
60
61 $query2 = mysqli_query($con, "SELECT * FROM $stableDays WHERE $sfieldSchedule = $sid ORDER BY typeday ASC, day ASC");
62
63 while ($row = mysqli_fetch_assoc($query2)) {
64 if (!isset($return["days"][$row["typeday"]]))
65 $return["days"][$row["typeday"]] = [];
66
67 $return["days"][$row["typeday"]][$row["day"]] = $row;
68 }
69 }
70
71 private static function _get($id, $table, $tableDays, $fieldSchedule) {
72 global $con;
73
74 $sid = (int)$id;
75 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
76 $stableDays = preg_replace("/[^A-Za-z0-9 ]/", '', $tableDays);
77 $sfieldSchedule = preg_replace("/[^A-Za-z0-9 ]/", '', $fieldSchedule);
78
79 $query = mysqli_query($con, "SELECT * FROM $stable WHERE id = $sid");
80
81 if ($query === false || !mysqli_num_rows($query)) return false;
82
83 $return = mysqli_fetch_assoc($query);
84
85 self::_addDaysToReturn($return, $stableDays, $sfieldSchedule, $sid);
86
87 return $return;
88 }
89
90 public static function getTemplate($id) {
91 return self::_get($id, "scheduletemplates", "scheduletemplatesdays", "template");
92 }
93
94 public static function getTemplates() {
95 global $con, $conf;
96
97 $query = mysqli_query($con, "SELECT * FROM scheduletemplates ORDER BY ".($conf["debug"] ? "id" : "name")." ASC");
98
99 $templates = [];
100
101 while ($row = mysqli_fetch_assoc($query)) {
102 $templates[] = $row;
103 }
104
105 return $templates;
106 }
107
108 public static function editTemplate($id, $name, $ibegins, $iends) {
109 global $con;
110
111 $sid = (int)$id;
112 $sname = db::sanitize($name);
113 $begins = new DateTime($ibegins);
114 $sbegins = (int)$begins->getTimestamp();
115 $ends = new DateTime($iends);
116 $sends = (int)$ends->getTimestamp();
117
118 if (!intervals::wellFormed([$sbegins, $sends])) return 2;
119
120 return (mysqli_query($con, "UPDATE scheduletemplates SET name = '$sname', begins = $sbegins, ends = $sends WHERE id = $sid LIMIT 1") ? 0 : 1);
121 }
122
123 public static function _remove($id, $table, $tableDays, $fieldSchedule) {
124 global $con;
125
126 $sid = (int)$id;
127 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
128 $stableDays = preg_replace("/[^A-Za-z0-9 ]/", '', $tableDays);
129 $sfieldSchedule = preg_replace("/[^A-Za-z0-9 ]/", '', $fieldSchedule);
130
131 return (mysqli_query($con, "DELETE FROM $stable WHERE id = $sid LIMIT 1") && mysqli_query($con, "DELETE FROM $stableDays WHERE $fieldSchedule = $sid"));
132 }
133
134 public static function removeTemplate($id) {
135 return self::_remove($id, "scheduletemplates", "scheduletemplatesdays", "template");
136 }
137
138 private static function _exists($id, $table) {
139 global $con;
140
141 $sid = (int)$id;
142 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
143
144 $query = mysqli_query($con, "SELECT id FROM $stable WHERE id = ".(int)$id);
145
146 return (mysqli_num_rows($query) > 0);
147 }
148
149 public static function templateExists($id) {
150 return self::_exists($id, "scheduletemplates");
151 }
152
153 public static function checkAddDayGeneric($begins, $ends, $beginsb, $endsb, $beginsl, $endsl) {
154 global $con;
155
156 $times = [];
157 $times["work"] = [$begins, $ends];
158 $times["breakfast"] = [$beginsb, $endsb];
159 $times["lunch"] = [$beginsl, $endsl];
160
161 foreach ($times as $time) {
162 if (intervals::wellFormed($time) === false) return 1;
163 }
164
165 if (intervals::measure($times["work"]) == 0) return 4;
166
167 if ((!intervals::isSubset($times["breakfast"], $times["work"]) && intervals::measure($times["breakfast"]) != 0) || (!intervals::isSubset($times["lunch"], $times["work"]) && intervals::measure($times["lunch"]) != 0)) return 2;
168
169 if (intervals::overlaps($times["breakfast"], $times["lunch"]) && intervals::measure($times["breakfast"]) != 0 && intervals::measure($times["lunch"]) != 0) return 3;
170
171 return 0;
172 }
173
174 private static function _checkAddDayParticular($id, $dow, $typeday, $table, $fieldSchedule) {
175 global $con;
176
177 $sid = (int)$id;
178 $sdow = (int)$dow;
179 $stypeday = (int)$typeday;
180 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
181 $sfieldSchedule = preg_replace("/[^A-Za-z0-9 ]/", '', $fieldSchedule);
182
183 $query = mysqli_query($con, "SELECT id FROM $stable WHERE $fieldSchedule = $sid AND day = $sdow AND typeday = $stypeday");
184
185 return (!mysqli_num_rows($query));
186 }
187
188 public static function checkAddDay2TemplateParticular($id, $dow, $typeday) {
189 return self::_checkAddDayParticular($id, $dow, $typeday, "scheduletemplatesdays", "template");
190 }
191
192 private static function _addDay($id, $dow, $typeday, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl, $table, $fieldSchedule) {
193 global $con;
194
195 $sid = (int)$id;
196 $sdow = (int)$dow;
197 $stypeday = (int)$typeday;
198 $sbegins = (int)$begins;
199 $sends = (int)$ends;
200 $sbeginsb = (int)$beginsb;
201 $sendsb = (int)$endsb;
202 $sbeginsl = (int)$beginsl;
203 $sendsl = (int)$endsl;
204 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
205 $sfieldSchedule = preg_replace("/[^A-Za-z0-9 ]/", '', $fieldSchedule);
206
207 return mysqli_query($con, "INSERT INTO $stable ($sfieldSchedule, day, typeday, beginswork, endswork, beginsbreakfast, endsbreakfast, beginslunch, endslunch) VALUES ($sid, $sdow, $stypeday, $sbegins, $sends, $sbeginsb, $sendsb, $sbeginsl, $sendsl)");
208 }
209
210 public static function addDay2Template($id, $dow, $typeday, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl) {
211 return self::_addDay($id, $dow, $typeday, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl, "scheduletemplatesdays", "template");
212 }
213
214 public static function _getDay($id, $table) {
215 global $con;
216
217 $sid = (int)$id;
218 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
219
220 $query = mysqli_query($con, "SELECT * FROM $stable WHERE id = $sid");
221
222 if (!mysqli_num_rows($query)) return false;
223
224 return mysqli_fetch_assoc($query);
225 }
226
227 public static function getTemplateDay($id) {
228 return self::_getDay($id, "scheduletemplatesdays");
229 global $con;
230 }
231
232 private static function _editDay($id, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl, $table) {
233 global $con;
234
235 $sid = (int)$id;
236 $sbegins = (int)$begins;
237 $sends = (int)$ends;
238 $sbeginsb = (int)$beginsb;
239 $sendsb = (int)$endsb;
240 $sbeginsl = (int)$beginsl;
241 $sendsl = (int)$endsl;
242 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
243
244 return mysqli_query($con, "UPDATE $stable SET beginswork = $sbegins, endswork = $sends, beginsbreakfast = $sbeginsb, endsbreakfast = $sendsb, beginslunch = $sbeginsl, endslunch = $sendsl WHERE id = $sid LIMIT 1");
245 }
246
247 public static function editTemplateDay($id, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl) {
248 return self::_editDay($id, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl, "scheduletemplatesdays");
249 }
250
251 private static function _removeDay($id, $table) {
252 global $con;
253
254 $sid = (int)$id;
255 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
256
257 return mysqli_query($con, "DELETE FROM $stable WHERE id = $sid LIMIT 1");
258 }
259
260 public static function removeTemplateDay($id) {
261 return self::_removeDay($id, "scheduletemplatesdays");
262 }
263
264 private static function _dayExists($id, $table) {
265 global $con;
266
267 $sid = (int)$id;
268 $stable = preg_replace("/[^A-Za-z0-9 ]/", '', $table);
269
270 $query = mysqli_query($con, "SELECT id FROM $stable WHERE id = $sid");
271
272 return (mysqli_num_rows($query) > 0);
273 }
274
275 public static function templateDayExists($id) {
276 return self::_dayExists($id, "scheduletemplatesdays");
277 }
278
279 // SCHEDULES:
280
281 public static function checkOverlap($worker, $begins, $ends, $sans = 0) {
282 global $con;
283
284 $sworker = (int)$worker;
285 $sbegins = (int)$begins;
286 $sends = (int)$ends;
287 $ssans = (int)$sans;
288
289 $query = mysqli_query($con, "SELECT * FROM schedules WHERE begins <= $sends AND ends >= $sbegins AND worker = $sworker".($sans == 0 ? "" : " AND id <> $ssans")." LIMIT 1");
290
291 return (mysqli_num_rows($query) > 0);
292 }
293
294 public static function get($id) {
295 return self::_get($id, "schedules", "schedulesdays", "schedule");
296 }
297
298 public static function getAll($id, $showNotActive = true) {
299 global $con, $conf;
300
301 $sid = (int)$id;
302
303 $query = mysqli_query($con, "SELECT * FROM schedules WHERE worker = $sid".($showNotActive ? "" : " AND active = 1")." ORDER BY ".($conf["debug"] ? "id ASC" : "begins DESC"));
304
305 $schedules = [];
306
307 while ($row = mysqli_fetch_assoc($query)) {
308 $schedules[] = $row;
309 }
310
311 return $schedules;
312 }
313
314 public static function getCurrent($id = "ME", $isWorker = false) {
315 global $con;
316
317 if ($id == "ME") $id = people::userData("id");
318 $sid = (int)$id;
319
320 $date = new DateTime(date("Y-m-d")."T00:00:00");
321 $timestamp = (int)$date->getTimestamp();
322
323 $query = mysqli_query($con, "SELECT s.* FROM schedules s ".($isWorker ? "WHERE s.worker = $sid" : "LEFT JOIN workers w ON s.worker = w.id WHERE w.person = $sid")." AND s.active = 1 AND s.begins <= $timestamp AND s.ends >= $timestamp");
324
325 $return = [];
326
327 while ($row = mysqli_fetch_assoc($query)) {
328 self::_addDaysToReturn($row, "schedulesdays", "schedule", $row["id"]);
329 $return[] = $row;
330 }
331
332 return $return;
333 }
334
335 public static function getWorkerScheduleStatus($id) {
336 $currentSchedules = self::getCurrent($id, true);
337 if ($currentSchedules === false || !count($currentSchedules)) return ["status" => self::STATUS_NO_ACTIVE_SCHEDULE];
338
339 $schedule =& $currentSchedules[0];
340
341 foreach (calendars::$workingTypes as $type) {
342 if (!isset($schedule["days"][$type]) || !count($schedule["days"][$type])) return ["status" => self::STATUS_HALFWAY_CONFIGURED_SCHEDULE, "schedule" => $schedule["id"]];
343 }
344
345 return ["status" => self::STATUS_ACTIVE_SCHEDULE, "schedule" => $schedule["id"]];
346 }
347
348 public static function add($worker, $ibegins, $iends, $active = 0, $alreadyTimestamp = false) {
349 global $con;
350
351 $sworker = (int)$worker;
352 $sactive = (int)$active;
353 if ($alreadyTimestamp) {
354 $sbegins = (int)$ibegins;
355 $sends = (int)$iends;
356 } else {
357 $begins = new DateTime($ibegins);
358 $sbegins = (int)$begins->getTimestamp();
359 $ends = new DateTime($iends);
360 $sends = (int)$ends->getTimestamp();
361 }
362
363 if (!intervals::wellFormed([$sbegins, $sends])) return 3;
364
365 if (self::checkOverlap($worker, $sbegins, $sends)) {
366 return 1;
367 }
368
369 return (mysqli_query($con, "INSERT INTO schedules (worker, begins, ends, active) VALUES ('$sworker', $sbegins, $sends, $sactive)") ? 0 : 2);
370 }
371
372 public static function edit($id, $ibegins, $iends) {
373 global $con;
374
375 $sid = (int)$id;
376 $begins = new DateTime($ibegins);
377 $sbegins = (int)$begins->getTimestamp();
378 $ends = new DateTime($iends);
379 $sends = (int)$ends->getTimestamp();
380
381 if (!intervals::wellFormed([$sbegins, $sends])) return 3;
382
383 $actual = self::get($sid);
384 if ($actual === false) return 4;
385
386 if (self::checkOverlap($actual["worker"], $sbegins, $sends, $sid)) {
387 return 1;
388 }
389
390 return (mysqli_query($con, "UPDATE schedules SET begins = $sbegins, ends = $sends WHERE id = $sid LIMIT 1") ? 0 : 2);
391 }
392
393 public static function remove($id) {
394 return self::_remove($id, "schedules", "schedulesdays", "schedule");
395 }
396
397 public static function switchActive($id, $value) {
398 global $con;
399
400 $sid = (int)$id;
401 $svalue = (int)$value;
402 if ($svalue > 1 || $svalue < 0) return false;
403
404 return mysqli_query($con, "UPDATE schedules SET active = $svalue WHERE id = $sid LIMIT 1");
405 }
406
407 public static function exists($id) {
408 return self::_exists($id, "schedules");
409 }
410
411 public static function checkAddDay2ScheduleParticular($id, $dow, $typeday) {
412 return self::_checkAddDayParticular($id, $dow, $typeday, "schedulesdays", "schedule");
413 }
414
415 public static function addDay2Schedule($id, $dow, $typeday, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl) {
416 return self::_addDay($id, $dow, $typeday, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl, "schedulesdays", "schedule");
417 }
418
419 public static function getDay($id) {
420 return self::_getDay($id, "schedulesdays");
421 global $con;
422 }
423
424 public static function editDay($id, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl) {
425 return self::_editDay($id, $begins, $ends, $beginsb, $endsb, $beginsl, $endsl, "schedulesdays");
426 }
427
428 public static function dayExists($id) {
429 return self::_dayExists($id, "schedulesdays");
430 }
431
432 public static function removeDay($id) {
433 return self::_removeDay($id, "schedulesdays");
434 }
435
436 public static function copyTemplate($template, $worker, $active) {
437 global $con;
438
439 $template = self::getTemplate($template);
440 if ($template === false) return 1;
441
442 $status = self::add($worker, $template["begins"], $template["ends"], $active, true);
443 if ($status != 0) return ($status + 1);
444
445 $id = mysqli_insert_id($con);
446
447 foreach ($template["days"] as $typeday) {
448 foreach ($typeday as $day) {
449 $status2 = self::addDay2Schedule($id, $day["day"], $day["typeday"], $day["beginswork"], $day["endswork"], $day["beginsbreakfast"], $day["endsbreakfast"], $day["beginslunch"], $day["endslunch"]);
450 if (!$status2) return -1;
451 }
452 }
453
454 return 0;
455 }
456}