blob: ae9589e7477866e08cce7aff5e463cf2cc6d4125 [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001<?php
2require_once("core.php");
3security::checkType(security::WORKER);
4security::checkWorkerUIEnabled();
5
6$isAdmin = security::isAllowed(security::ADMIN);
7
8$mainURL = (security::isAdminView() ? "export.php" : "export4worker.php");
9
10if (!security::checkParams("GET", [
11 ["begins", security::PARAM_ISDATE],
12 ["ends", security::PARAM_ISDATE],
13 ["workers", security::PARAM_ISARRAY],
14 ["format", security::PARAM_ISINT]
15])) {
16 security::go($mainURL."?msg=empty");
17}
18
19$ignoreempty = (isset($_GET["ignoreempty"]) && $_GET["ignoreempty"] == 1);
20$labelinvalid = (isset($_GET["labelinvalid"]) && $_GET["labelinvalid"] == 1);
21$showvalidated = (isset($_GET["showvalidated"]) && $_GET["showvalidated"] == 1);
22$shownotvalidated = (isset($_GET["shownotvalidated"]) && $_GET["shownotvalidated"] == 1);
23
24$begins = new DateTime($_GET["begins"]);
25$ends = new DateTime($_GET["ends"]);
26$interval = new DateInterval("P1D");
27
28if (!intervals::wellFormed([$begins, $ends])) {
29 security::go($mainURL."?msg=inverted");
30}
31
32$date = new DateTime(date("Y-m-d")."T00:00:00");
33$interval = new DateInterval("P1D");
34$date->sub($interval);
35
36if ($ends->diff($date)->invert !== 0) {
37 security::go($mainURL."?msg=forecastingthefutureisimpossible");
38}
39
40$companies = companies::getAll(false, true);
41if ($companies === false) {
42 security::go($mainURL."?msg=unexpected");
43}
44
45$filenameDate = $begins->format("Ymd")."_".$ends->format("Ymd");
46
47if (!$isAdmin && !in_array($_GET["format"], export::$workerFormats)) {
48 echo "Todavía no implementado.\n";
49 exit();
50}
51
52switch ($_GET["format"]) {
53 case export::FORMAT_PDF:
54 case export::FORMAT_DETAILEDPDF:
55 require_once("lib/fpdf/fpdf.php");
56 require_once("lib/fpdf-easytable/exfpdf.php");
57 require_once("lib/fpdf-easytable/easyTable.php");
58
59 $actualTime = time();
60
61 class PDF extends EXFPDF {
62 function Footer() {
63 global $actualTime;
64
65 $this->SetFont('Arial','I',10);
66 $this->SetY(-20);
67 $this->Cell(0, 10, export::convert("Generado: ".strftime("%d %b %Y %T", $actualTime)), 0, 0, 'L');
68 $this->SetY(-20);
69 $this->Cell(0, 10, $this->PageNo().'/{nb}', 0, 0, 'R');
70 }
71 }
72
73 $pdf = new PDF();
74 $pdf->SetCompression(true);
75 $pdf->SetCreator(export::convert($conf["appName"]));
76 $pdf->SetTitle(export::convert("Registro".($showvalidated && !$shownotvalidated ? " (validados)" : "").(!$showvalidated && $shownotvalidated ? " (no validados)" : "")));
77 $pdf->SetAutoPageBreak(false, 22);
78 $pdf->AliasNbPages();
79 $pdf->SetFont('Arial','',12);
80
81 $headerCells = ["Fecha", "Inicio jornada", "Fin jornada", "Desayuno", "Comida", ""];
82 $headerCells = array_map(function($value) {
83 return export::convert($value);
84 }, $headerCells);
85 $spacingDayRow = "%{18, 18, 18, 19, 19, 8}";
86
87 foreach ($_GET["workers"] as $workerid) {
88 $worker = workers::get($workerid);
89 if ($worker === false || (!$isAdmin && $worker["person"] != $_SESSION["id"])) continue;
90
91 $days = export::getDays($worker["id"], $begins->getTimestamp(), $ends->getTimestamp(), $showvalidated, $shownotvalidated);
92
93 if (count($days) || !$ignoreempty) {
94 $pdf->AddPage();
95 $pdf->SetMargins(17, 17);
96 $pdf->SetY(17);
97
98 $header = new easyTable($pdf, 1, 'border-width: 0.01; border: 0; align: L;');
99 $header->easyCell(export::convert($worker["name"].(!empty($worker["dni"]) ? " (".$worker["dni"].")" : "")), 'font-style:B;');
100 $header->printRow();
101 $header->easyCell(export::convert($worker["companyname"].(!empty($companies[$worker["company"]]["cif"]) ? " (CIF: ".$companies[$worker["company"]]["cif"].")" : "")));
102 $header->printRow();
103 $header->endTable(6);
104 }
105
106 if (count($days)) {
107 $totalEffectiveTime = 0;
108 $totalWorkTime = 0;
109 $incidentsTime = [];
110
111 $table = new easyTable($pdf, $spacingDayRow, 'border: "TB"; border-width: 0.15;');
112 foreach ($headerCells as $i => $cell) {
113 $table->easyCell($cell, 'font-style: B;'.($i == 0 ? "" : " align: C;"));
114 }
115 $table->printRow(true);
116 $table->endTable(0);
117
118 foreach ($days as $timestamp => $day) {
119 $issetSchedule = isset($day["schedule"]);
120 $showSchedule = $issetSchedule;
121 if ($showSchedule && isset($day["incidents"])) {
122 foreach ($day["incidents"] as $incident) {
123 if ($incident["allday"] == true && $incident["typepresent"] == 0) {
124 $showSchedule = false;
125 break;
126 }
127 }
128 }
129
130 $workInt = ($issetSchedule ? [$day["schedule"]["beginswork"], $day["schedule"]["endswork"]] : [incidents::STARTOFDAY, incidents::STARTOFDAY]);
131 $notWorkIntA = ($issetSchedule ? [incidents::STARTOFDAY, $day["schedule"]["beginswork"]] : [incidents::STARTOFDAY, incidents::ENDOFDAY]);
132 $notWorkIntB = ($issetSchedule ? [$day["schedule"]["endswork"], incidents::ENDOFDAY] : [incidents::ENDOFDAY, incidents::ENDOFDAY]);
133 $breakfastInt = ($issetSchedule ? [$day["schedule"]["beginsbreakfast"], $day["schedule"]["endsbreakfast"]] : [incidents::STARTOFDAY, incidents::STARTOFDAY]);
134 $lunchInt = ($issetSchedule ? [$day["schedule"]["beginslunch"], $day["schedule"]["endslunch"]] : [incidents::STARTOFDAY, incidents::STARTOFDAY]);
135
136 $effectiveTime = intervals::measure($workInt) - (intervals::measure($breakfastInt) + intervals::measure($lunchInt));
137
138 $totalWorkTime += $effectiveTime;
139
140 if (isset($day["incidents"])) {
141 foreach ($day["incidents"] as &$incident) {
142 $incidentInt = [$incident["begins"], $incident["ends"]];
143
144 $incidentTime = 0;
145
146 if ($incident["typepresent"] == 1) {
147 $incidentTime = intervals::measureIntersection($incidentInt, $notWorkIntA) + intervals::measureIntersection($incidentInt, $notWorkIntB) + intervals::measureIntersection($incidentInt, $breakfastInt) + intervals::measureIntersection($incidentInt, $lunchInt);
148 $effectiveTime = $effectiveTime + $incidentTime;
149
150 $incidentTime = -$incidentTime;
151 } else {
152 $incidentTime = intervals::measureIntersection($incidentInt, $workInt) - ($conf["pdfs"]["workersAlwaysHaveBreakfastAndLunch"] ? 0 : (intervals::measureIntersection($incidentInt, $breakfastInt) + intervals::measureIntersection($incidentInt, $lunchInt)));
153 $effectiveTime = $effectiveTime - $incidentTime;
154 }
155
156 $incidentsTime[$incident["typename"]] = (isset($incidentsTime[$incident["typename"]]) ? $incidentsTime[$incident["typename"]] : 0) + $incidentTime;
157 }
158 }
159
160 $effectiveTime = max(incidents::STARTOFDAY, min($effectiveTime, incidents::ENDOFDAY));
161 $totalEffectiveTime += $effectiveTime;
162
163 $labelAsInvalid = ($shownotvalidated && isset($day["schedule"]) && $day["schedule"]["state"] === registry::STATE_REGISTERED);
164
165 $table = new easyTable($pdf, $spacingDayRow, 'border: "BT";'.(isset($day["incidents"]) ? ' border-width: 0.07; border-color: #555;' : ' border-width: 0.15;').($labelAsInvalid && $labelinvalid ? ' font-color: #F00;' : ''));
166 $table->easyCell(export::convert(date("d/m/Y", $timestamp).($labelAsInvalid ? " (nv)" : "")));
167 $table->easyCell(export::convert(($showSchedule ? schedules::sec2time($day["schedule"]["beginswork"]) : "-")), 'align: C;');
168 $table->easyCell(export::convert(($showSchedule ? schedules::sec2time($day["schedule"]["endswork"]) : "-")), 'align: C;');
169 $table->easyCell(export::convert(($showSchedule ? (intervals::measure($breakfastInt) == 0 ? "-" : (!$conf["pdfs"]["showExactTimeForBreakfastAndLunch"] ? export::sec2hours(intervals::measure($breakfastInt)) : schedules::sec2time($day["schedule"]["beginsbreakfast"])." - ".schedules::sec2time($day["schedule"]["endsbreakfast"]))) : "-")), 'align: C;');
170 $table->easyCell(export::convert(($showSchedule ? (intervals::measure($lunchInt) == 0 ? "-" : (!$conf["pdfs"]["showExactTimeForBreakfastAndLunch"] ? export::sec2hours(intervals::measure($lunchInt)) : schedules::sec2time($day["schedule"]["beginslunch"])." - ".schedules::sec2time($day["schedule"]["endslunch"]))) : "-")), 'align: C;');
171 $table->easyCell(export::convert(export::sec2hours($effectiveTime)), 'font-style: B; align: R;');
172 $table->printRow();
173 $table->endTable(0);
174
175 if (isset($day["incidents"])) {
176 $incidentstable = new easyTable($pdf, "%{7, 15, 20, 20, 38}", 'border: "BT"; border-width: 0.15; font-color: #555;');
177 foreach ($day["incidents"] as &$incident) {
178 $labelAsInvalid = ($incident["state"] === incidents::STATE_REGISTERED);
179
180 if ($labelAsInvalid && $labelinvalid) $incidentstable->rowStyle('font-color: #F00;');
181 $incidentstable->easyCell("");
182 $incidentstable->easyCell(export::convert("Incidencia:"), 'font-style: B;');
183 $incidentstable->easyCell(export::convert($incident["typename"]), 'align: C; font-size: 11;');
184 $incidentstable->easyCell(export::convert("(".(($incident["begins"] == 0 && $incident["ends"] == incidents::ENDOFDAY) ? "todo el día" : schedules::sec2time($incident["begins"])." - ".schedules::sec2time($incident["ends"])).")"), 'align: C;');
185 $incidentstable->easyCell(export::convert((!empty($incident["details"]) ? "Obs.: ".$incident["details"] : "").($labelAsInvalid ? "\n(No validada)" : "")), 'font-size: 10;');
186 $incidentstable->printRow();
187 }
188 $incidentstable->endTable(0);
189 }
190 }
191
192 if ($_GET["format"] == export::FORMAT_DETAILEDPDF) {
193 $pdf->Ln();
194 $pdf->Ln();
195 $table = new easyTable($pdf, "%{77, 23}", 'align: R; width: 100; border: "BT"; border-width: 0.15;');
196
197 $table->easyCell(export::convert("Tiempo de trabajo programado"));
198 $table->easyCell(export::convert(export::sec2hours($totalWorkTime)), 'align: R;');
199 $table->printRow();
200
201 foreach ($incidentsTime as $incidentName => $incidentTime) {
202 $table->easyCell(export::convert($incidentName));
203 $table->easyCell(export::convert(($incidentTime <= 0 ? "+" : "\u{2013}")." ".export::sec2hours(abs($incidentTime))), 'align: R;');
204 $table->printRow();
205 }
206
207 $table->easyCell(export::convert("Tiempo trabajado"), 'font-style: B;');
208 $table->easyCell(export::convert(export::sec2hours($totalEffectiveTime)), 'align: R; font-style: B;');
209 $table->printRow();
210
211 $table->endTable(0);
212 }
213 } elseif (!$ignoreempty) {
214 $pdf->Cell(0, 0, "No hay datos para este trabajador.", 0, 0, 'C');
215 }
216 }
217
218 $pdf->Output("I", "registrohorario_".$filenameDate.".pdf");
219 break;
220
221 case export::FORMAT_CSV_SCHEDULES:
222 case export::FORMAT_CSV_INCIDENTS:
223 $isSchedules = ($_GET["format"] == export::FORMAT_CSV_SCHEDULES);
224 $field = ($isSchedules ? "schedule" : "incidents");
225 header("Content-Type: text/csv");
226 header("Content-Disposition: attachment;filename=".($isSchedules ? "schedules_".$filenameDate.".csv" : "incidents_".$filenameDate.".csv"));
227
228 $array = [];
229
230 $array[] = ($isSchedules ? export::$schedulesFields : export::$incidentsFields);
231
232 foreach ($_GET["workers"] as $workerid) {
233 $worker = workers::get($workerid);
234 if ($worker === false || (!$isAdmin && $worker["person"] != $_SESSION["id"])) continue;
235
236 $days = export::getDays($worker["id"], $begins->getTimestamp(), $ends->getTimestamp(), true, true);
237
238 foreach ($days as &$day) {
239 if (isset($day[$field])) {
240 if ($isSchedules) {
241 $schedule = [];
242 foreach (export::$schedulesFields as $i => $key) {
243 $types = ["breakfast", "lunch"];
244 $typesNotDefined = [];
245 foreach ($types as $type) {
246 if (intervals::measure([$day[$field]["begins".$type], $day[$field]["ends".$type]]) == 0) {
247 $typesNotDefined[] = "begins".$type;
248 $typesNotDefined[] = "ends".$type;
249 }
250 }
251
252 switch ($key) {
253 case "worker":
254 $schedule[$i] = $worker["name"];
255 break;
256
257 case "company":
258 $schedule[$i] = $worker["companyname"];
259 break;
260
261 case "workerid":
262 $schedule[$i] = $worker["id"];
263 break;
264
265 case "dni":
266 $schedule[$i] = $worker["dni"];
267 break;
268
269 case "day":
270 $schedule[$i] = date("d/m/Y", $day[$field][$key]);
271 break;
272
273 case "state":
274 $schedule[$i] = (registry::$stateTooltips[$day[$field][$key]]);
275 break;
276
277 case "beginswork":
278 case "endswork":
279 case "beginsbreakfast":
280 case "endsbreakfast":
281 case "beginslunch":
282 case "endslunch":
283 $schedule[$i] = (in_array($key, $typesNotDefined) ? "-" : schedules::sec2time($day[$field][$key]));
284 break;
285
286 default:
287 $schedule[$i] = $day[$field][$key];
288 }
289 }
290 $array[] = $schedule;
291 } else {
292 foreach ($day[$field] as &$incident) {
293 $convIncident = [];
294 foreach (export::$incidentsFields as $i => $key) {
295 switch ($key) {
296 case "worker":
297 $convIncident[$i] = $worker["name"];
298 break;
299
300 case "company":
301 $convIncident[$i] = $worker["companyname"];
302 break;
303
304 case "workerid":
305 $convIncident[$i] = $worker["id"];
306 break;
307
308 case "dni":
309 $convIncident[$i] = $worker["dni"];
310 break;
311
312 case "creator":
313 case "updatedby":
314 case "confirmedby":
315 $convIncident[$i] = (($key == "updatedby" && $incident["updatestate"] != 1) ? "-" : people::userData("name", $incident[$key]));
316 break;
317
318 case "day":
319 $convIncident[$i] = date("d/m/Y", $incident[$key]);
320 break;
321
322 case "begins":
323 case "ends":
324 $convIncident[$i] = ($incident["allday"] == 1 ? "-" : schedules::sec2time($incident[$key]));
325 break;
326
327 case "updated":
328 case "verified":
329 case "typepresent":
330 case "typepaid":
331 if ($key == "updated") $key = "updatestate";
332 $convIncident[$i] = ($incident[$key] == -1 ? "-" : ($incident[$key] == 1 ? visual::YES : visual::NO));
333 break;
334
335 case "allday":
336 $convIncident[$i] = ($incident[$key] == 1 ? visual::YES : visual::NO);
337 break;
338
339 case "state":
340 $convIncident[$i] = (incidents::$stateTooltips[$incident[$key]]);
341 break;
342
343 case "type":
344 $convIncident[$i] = $incident["typename"];
345 break;
346
347 default:
348 $convIncident[$i] = $incident[$key];
349 }
350 }
351 $array[] = $convIncident;
352 }
353 }
354 }
355 }
356 }
357
358 if (!count($array)) exit();
359
360 $df = fopen("php://output", 'w');
361
362 foreach ($array as $row) fputcsv($df, $row);
363
364 fclose($df);
365 break;
366
367 default:
368 header("Content-Type: text/plain;");
369 echo "Todavía no implementado.\n";
370}