Project import generated by Copybara.
GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
diff --git a/src/doexport.php b/src/doexport.php
new file mode 100644
index 0000000..ae9589e
--- /dev/null
+++ b/src/doexport.php
@@ -0,0 +1,370 @@
+<?php
+require_once("core.php");
+security::checkType(security::WORKER);
+security::checkWorkerUIEnabled();
+
+$isAdmin = security::isAllowed(security::ADMIN);
+
+$mainURL = (security::isAdminView() ? "export.php" : "export4worker.php");
+
+if (!security::checkParams("GET", [
+ ["begins", security::PARAM_ISDATE],
+ ["ends", security::PARAM_ISDATE],
+ ["workers", security::PARAM_ISARRAY],
+ ["format", security::PARAM_ISINT]
+])) {
+ security::go($mainURL."?msg=empty");
+}
+
+$ignoreempty = (isset($_GET["ignoreempty"]) && $_GET["ignoreempty"] == 1);
+$labelinvalid = (isset($_GET["labelinvalid"]) && $_GET["labelinvalid"] == 1);
+$showvalidated = (isset($_GET["showvalidated"]) && $_GET["showvalidated"] == 1);
+$shownotvalidated = (isset($_GET["shownotvalidated"]) && $_GET["shownotvalidated"] == 1);
+
+$begins = new DateTime($_GET["begins"]);
+$ends = new DateTime($_GET["ends"]);
+$interval = new DateInterval("P1D");
+
+if (!intervals::wellFormed([$begins, $ends])) {
+ security::go($mainURL."?msg=inverted");
+}
+
+$date = new DateTime(date("Y-m-d")."T00:00:00");
+$interval = new DateInterval("P1D");
+$date->sub($interval);
+
+if ($ends->diff($date)->invert !== 0) {
+ security::go($mainURL."?msg=forecastingthefutureisimpossible");
+}
+
+$companies = companies::getAll(false, true);
+if ($companies === false) {
+ security::go($mainURL."?msg=unexpected");
+}
+
+$filenameDate = $begins->format("Ymd")."_".$ends->format("Ymd");
+
+if (!$isAdmin && !in_array($_GET["format"], export::$workerFormats)) {
+ echo "Todavía no implementado.\n";
+ exit();
+}
+
+switch ($_GET["format"]) {
+ case export::FORMAT_PDF:
+ case export::FORMAT_DETAILEDPDF:
+ require_once("lib/fpdf/fpdf.php");
+ require_once("lib/fpdf-easytable/exfpdf.php");
+ require_once("lib/fpdf-easytable/easyTable.php");
+
+ $actualTime = time();
+
+ class PDF extends EXFPDF {
+ function Footer() {
+ global $actualTime;
+
+ $this->SetFont('Arial','I',10);
+ $this->SetY(-20);
+ $this->Cell(0, 10, export::convert("Generado: ".strftime("%d %b %Y %T", $actualTime)), 0, 0, 'L');
+ $this->SetY(-20);
+ $this->Cell(0, 10, $this->PageNo().'/{nb}', 0, 0, 'R');
+ }
+ }
+
+ $pdf = new PDF();
+ $pdf->SetCompression(true);
+ $pdf->SetCreator(export::convert($conf["appName"]));
+ $pdf->SetTitle(export::convert("Registro".($showvalidated && !$shownotvalidated ? " (validados)" : "").(!$showvalidated && $shownotvalidated ? " (no validados)" : "")));
+ $pdf->SetAutoPageBreak(false, 22);
+ $pdf->AliasNbPages();
+ $pdf->SetFont('Arial','',12);
+
+ $headerCells = ["Fecha", "Inicio jornada", "Fin jornada", "Desayuno", "Comida", ""];
+ $headerCells = array_map(function($value) {
+ return export::convert($value);
+ }, $headerCells);
+ $spacingDayRow = "%{18, 18, 18, 19, 19, 8}";
+
+ foreach ($_GET["workers"] as $workerid) {
+ $worker = workers::get($workerid);
+ if ($worker === false || (!$isAdmin && $worker["person"] != $_SESSION["id"])) continue;
+
+ $days = export::getDays($worker["id"], $begins->getTimestamp(), $ends->getTimestamp(), $showvalidated, $shownotvalidated);
+
+ if (count($days) || !$ignoreempty) {
+ $pdf->AddPage();
+ $pdf->SetMargins(17, 17);
+ $pdf->SetY(17);
+
+ $header = new easyTable($pdf, 1, 'border-width: 0.01; border: 0; align: L;');
+ $header->easyCell(export::convert($worker["name"].(!empty($worker["dni"]) ? " (".$worker["dni"].")" : "")), 'font-style:B;');
+ $header->printRow();
+ $header->easyCell(export::convert($worker["companyname"].(!empty($companies[$worker["company"]]["cif"]) ? " (CIF: ".$companies[$worker["company"]]["cif"].")" : "")));
+ $header->printRow();
+ $header->endTable(6);
+ }
+
+ if (count($days)) {
+ $totalEffectiveTime = 0;
+ $totalWorkTime = 0;
+ $incidentsTime = [];
+
+ $table = new easyTable($pdf, $spacingDayRow, 'border: "TB"; border-width: 0.15;');
+ foreach ($headerCells as $i => $cell) {
+ $table->easyCell($cell, 'font-style: B;'.($i == 0 ? "" : " align: C;"));
+ }
+ $table->printRow(true);
+ $table->endTable(0);
+
+ foreach ($days as $timestamp => $day) {
+ $issetSchedule = isset($day["schedule"]);
+ $showSchedule = $issetSchedule;
+ if ($showSchedule && isset($day["incidents"])) {
+ foreach ($day["incidents"] as $incident) {
+ if ($incident["allday"] == true && $incident["typepresent"] == 0) {
+ $showSchedule = false;
+ break;
+ }
+ }
+ }
+
+ $workInt = ($issetSchedule ? [$day["schedule"]["beginswork"], $day["schedule"]["endswork"]] : [incidents::STARTOFDAY, incidents::STARTOFDAY]);
+ $notWorkIntA = ($issetSchedule ? [incidents::STARTOFDAY, $day["schedule"]["beginswork"]] : [incidents::STARTOFDAY, incidents::ENDOFDAY]);
+ $notWorkIntB = ($issetSchedule ? [$day["schedule"]["endswork"], incidents::ENDOFDAY] : [incidents::ENDOFDAY, incidents::ENDOFDAY]);
+ $breakfastInt = ($issetSchedule ? [$day["schedule"]["beginsbreakfast"], $day["schedule"]["endsbreakfast"]] : [incidents::STARTOFDAY, incidents::STARTOFDAY]);
+ $lunchInt = ($issetSchedule ? [$day["schedule"]["beginslunch"], $day["schedule"]["endslunch"]] : [incidents::STARTOFDAY, incidents::STARTOFDAY]);
+
+ $effectiveTime = intervals::measure($workInt) - (intervals::measure($breakfastInt) + intervals::measure($lunchInt));
+
+ $totalWorkTime += $effectiveTime;
+
+ if (isset($day["incidents"])) {
+ foreach ($day["incidents"] as &$incident) {
+ $incidentInt = [$incident["begins"], $incident["ends"]];
+
+ $incidentTime = 0;
+
+ if ($incident["typepresent"] == 1) {
+ $incidentTime = intervals::measureIntersection($incidentInt, $notWorkIntA) + intervals::measureIntersection($incidentInt, $notWorkIntB) + intervals::measureIntersection($incidentInt, $breakfastInt) + intervals::measureIntersection($incidentInt, $lunchInt);
+ $effectiveTime = $effectiveTime + $incidentTime;
+
+ $incidentTime = -$incidentTime;
+ } else {
+ $incidentTime = intervals::measureIntersection($incidentInt, $workInt) - ($conf["pdfs"]["workersAlwaysHaveBreakfastAndLunch"] ? 0 : (intervals::measureIntersection($incidentInt, $breakfastInt) + intervals::measureIntersection($incidentInt, $lunchInt)));
+ $effectiveTime = $effectiveTime - $incidentTime;
+ }
+
+ $incidentsTime[$incident["typename"]] = (isset($incidentsTime[$incident["typename"]]) ? $incidentsTime[$incident["typename"]] : 0) + $incidentTime;
+ }
+ }
+
+ $effectiveTime = max(incidents::STARTOFDAY, min($effectiveTime, incidents::ENDOFDAY));
+ $totalEffectiveTime += $effectiveTime;
+
+ $labelAsInvalid = ($shownotvalidated && isset($day["schedule"]) && $day["schedule"]["state"] === registry::STATE_REGISTERED);
+
+ $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;' : ''));
+ $table->easyCell(export::convert(date("d/m/Y", $timestamp).($labelAsInvalid ? " (nv)" : "")));
+ $table->easyCell(export::convert(($showSchedule ? schedules::sec2time($day["schedule"]["beginswork"]) : "-")), 'align: C;');
+ $table->easyCell(export::convert(($showSchedule ? schedules::sec2time($day["schedule"]["endswork"]) : "-")), 'align: C;');
+ $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;');
+ $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;');
+ $table->easyCell(export::convert(export::sec2hours($effectiveTime)), 'font-style: B; align: R;');
+ $table->printRow();
+ $table->endTable(0);
+
+ if (isset($day["incidents"])) {
+ $incidentstable = new easyTable($pdf, "%{7, 15, 20, 20, 38}", 'border: "BT"; border-width: 0.15; font-color: #555;');
+ foreach ($day["incidents"] as &$incident) {
+ $labelAsInvalid = ($incident["state"] === incidents::STATE_REGISTERED);
+
+ if ($labelAsInvalid && $labelinvalid) $incidentstable->rowStyle('font-color: #F00;');
+ $incidentstable->easyCell("");
+ $incidentstable->easyCell(export::convert("Incidencia:"), 'font-style: B;');
+ $incidentstable->easyCell(export::convert($incident["typename"]), 'align: C; font-size: 11;');
+ $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;');
+ $incidentstable->easyCell(export::convert((!empty($incident["details"]) ? "Obs.: ".$incident["details"] : "").($labelAsInvalid ? "\n(No validada)" : "")), 'font-size: 10;');
+ $incidentstable->printRow();
+ }
+ $incidentstable->endTable(0);
+ }
+ }
+
+ if ($_GET["format"] == export::FORMAT_DETAILEDPDF) {
+ $pdf->Ln();
+ $pdf->Ln();
+ $table = new easyTable($pdf, "%{77, 23}", 'align: R; width: 100; border: "BT"; border-width: 0.15;');
+
+ $table->easyCell(export::convert("Tiempo de trabajo programado"));
+ $table->easyCell(export::convert(export::sec2hours($totalWorkTime)), 'align: R;');
+ $table->printRow();
+
+ foreach ($incidentsTime as $incidentName => $incidentTime) {
+ $table->easyCell(export::convert($incidentName));
+ $table->easyCell(export::convert(($incidentTime <= 0 ? "+" : "\u{2013}")." ".export::sec2hours(abs($incidentTime))), 'align: R;');
+ $table->printRow();
+ }
+
+ $table->easyCell(export::convert("Tiempo trabajado"), 'font-style: B;');
+ $table->easyCell(export::convert(export::sec2hours($totalEffectiveTime)), 'align: R; font-style: B;');
+ $table->printRow();
+
+ $table->endTable(0);
+ }
+ } elseif (!$ignoreempty) {
+ $pdf->Cell(0, 0, "No hay datos para este trabajador.", 0, 0, 'C');
+ }
+ }
+
+ $pdf->Output("I", "registrohorario_".$filenameDate.".pdf");
+ break;
+
+ case export::FORMAT_CSV_SCHEDULES:
+ case export::FORMAT_CSV_INCIDENTS:
+ $isSchedules = ($_GET["format"] == export::FORMAT_CSV_SCHEDULES);
+ $field = ($isSchedules ? "schedule" : "incidents");
+ header("Content-Type: text/csv");
+ header("Content-Disposition: attachment;filename=".($isSchedules ? "schedules_".$filenameDate.".csv" : "incidents_".$filenameDate.".csv"));
+
+ $array = [];
+
+ $array[] = ($isSchedules ? export::$schedulesFields : export::$incidentsFields);
+
+ foreach ($_GET["workers"] as $workerid) {
+ $worker = workers::get($workerid);
+ if ($worker === false || (!$isAdmin && $worker["person"] != $_SESSION["id"])) continue;
+
+ $days = export::getDays($worker["id"], $begins->getTimestamp(), $ends->getTimestamp(), true, true);
+
+ foreach ($days as &$day) {
+ if (isset($day[$field])) {
+ if ($isSchedules) {
+ $schedule = [];
+ foreach (export::$schedulesFields as $i => $key) {
+ $types = ["breakfast", "lunch"];
+ $typesNotDefined = [];
+ foreach ($types as $type) {
+ if (intervals::measure([$day[$field]["begins".$type], $day[$field]["ends".$type]]) == 0) {
+ $typesNotDefined[] = "begins".$type;
+ $typesNotDefined[] = "ends".$type;
+ }
+ }
+
+ switch ($key) {
+ case "worker":
+ $schedule[$i] = $worker["name"];
+ break;
+
+ case "company":
+ $schedule[$i] = $worker["companyname"];
+ break;
+
+ case "workerid":
+ $schedule[$i] = $worker["id"];
+ break;
+
+ case "dni":
+ $schedule[$i] = $worker["dni"];
+ break;
+
+ case "day":
+ $schedule[$i] = date("d/m/Y", $day[$field][$key]);
+ break;
+
+ case "state":
+ $schedule[$i] = (registry::$stateTooltips[$day[$field][$key]]);
+ break;
+
+ case "beginswork":
+ case "endswork":
+ case "beginsbreakfast":
+ case "endsbreakfast":
+ case "beginslunch":
+ case "endslunch":
+ $schedule[$i] = (in_array($key, $typesNotDefined) ? "-" : schedules::sec2time($day[$field][$key]));
+ break;
+
+ default:
+ $schedule[$i] = $day[$field][$key];
+ }
+ }
+ $array[] = $schedule;
+ } else {
+ foreach ($day[$field] as &$incident) {
+ $convIncident = [];
+ foreach (export::$incidentsFields as $i => $key) {
+ switch ($key) {
+ case "worker":
+ $convIncident[$i] = $worker["name"];
+ break;
+
+ case "company":
+ $convIncident[$i] = $worker["companyname"];
+ break;
+
+ case "workerid":
+ $convIncident[$i] = $worker["id"];
+ break;
+
+ case "dni":
+ $convIncident[$i] = $worker["dni"];
+ break;
+
+ case "creator":
+ case "updatedby":
+ case "confirmedby":
+ $convIncident[$i] = (($key == "updatedby" && $incident["updatestate"] != 1) ? "-" : people::userData("name", $incident[$key]));
+ break;
+
+ case "day":
+ $convIncident[$i] = date("d/m/Y", $incident[$key]);
+ break;
+
+ case "begins":
+ case "ends":
+ $convIncident[$i] = ($incident["allday"] == 1 ? "-" : schedules::sec2time($incident[$key]));
+ break;
+
+ case "updated":
+ case "verified":
+ case "typepresent":
+ case "typepaid":
+ if ($key == "updated") $key = "updatestate";
+ $convIncident[$i] = ($incident[$key] == -1 ? "-" : ($incident[$key] == 1 ? visual::YES : visual::NO));
+ break;
+
+ case "allday":
+ $convIncident[$i] = ($incident[$key] == 1 ? visual::YES : visual::NO);
+ break;
+
+ case "state":
+ $convIncident[$i] = (incidents::$stateTooltips[$incident[$key]]);
+ break;
+
+ case "type":
+ $convIncident[$i] = $incident["typename"];
+ break;
+
+ default:
+ $convIncident[$i] = $incident[$key];
+ }
+ }
+ $array[] = $convIncident;
+ }
+ }
+ }
+ }
+ }
+
+ if (!count($array)) exit();
+
+ $df = fopen("php://output", 'w');
+
+ foreach ($array as $row) fputcsv($df, $row);
+
+ fclose($df);
+ break;
+
+ default:
+ header("Content-Type: text/plain;");
+ echo "Todavía no implementado.\n";
+}