<?php
namespace App\Controller;
use App\Entity\Incidencia;
use App\Entity\Periodo;
use App\Entity\Usuario;
use App\Form\IncidenciaFiltroType;
use App\Form\IncidenciaType;
use App\Form\ReporteType;
use App\Service\DocumentoPDF;
use Box\Spout\Common\Exception\InvalidArgumentException;
use Box\Spout\Common\Exception\IOException;
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Writer\Exception\WriterNotOpenedException;
use DateInterval;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Routing\Annotation\Route;
use TCPDF;
//#[Route('/incidencia')]
/**
* @Route("/incidencia")
*/
class IncidenciaController extends AbstractController
{
public EntityManagerInterface $emi;
public function __construct(EntityManagerInterface $entityManager)
{
$this->emi = $entityManager;
}
//#[Route('/', name: 'app_incidencia_index', methods: ['GET'])]
/**
* @Route("/", name= "app_incidencia_index", methods= {"GET", "POST"})
* @param Request $request
* @return Response
*/
public function index(Request $request): Response
{
$perfil = $request->getSession()->get('perfilLecciones');
$nivel = $perfil[1]["nivel"];
if ($nivel == 0) {
$this->addFlash('danger', 'El acceso al módulo de "Lecciones" está restringido.');
return $this->redirectToRoute('homepage');
}
/** @var Usuario $user */
$user = $this->getUser();
$incidencias = "";
$perSession = $request->getSession()->get('periodoLecciones');
$perSession = $this->emi->getRepository(Periodo::class)->findOneBy(['idPrd' => $perSession->getIdPrd()]);
# Formulario de filtro de lecciones aprendidas
($nivel == 2) ? $uni = true : $uni = false;
$form = $this->createForm(IncidenciaFiltroType::class, null, ['uni' => $uni, 'periodo' => $perSession]);
$form->handleRequest($request);
$periodo = $form['periodo']->getData();
$tema = $form['tema']->getData();
$unidad = (isset($form['unidad'])) ? $form['unidad']->getData() : $user->getUnidad();
if ($request->isMethod('POST')) {
$incidencias = $this->emi->getRepository(Incidencia::class)->filtroLecciones($periodo, $unidad, $tema);
$data = [];
$estatus = "";
$estatusd = "";
foreach ($incidencias as $incidencia) {
$ver = $this->generateUrl('app_incidencia_show', ['idInc' => $incidencia->getIdInc()]);
$editar = $this->generateUrl('app_incidencia_edit', ['idInc' => $incidencia->getIdInc()]);
if ($incidencia->getAtendidoDir() == 0) {
$estatusd = '<span class="badge bg-gradient-primary d-block">P</span>';
}
if ($incidencia->getAtendidoDir() == 1) {
$estatusd = '<span class="badge bg-gradient-yellow d-block">S</span>';
}
if ($incidencia->getAtendidoDir() == 2) {
$estatusd = '<span class="badge bg-gradient-success d-block">A</span>';
}
if ($incidencia->getAtendido() == 0) {
$estatus = '<span class="badge bg-gradient-primary d-block">Pendiente</span>';
}
if ($incidencia->getAtendido() == 1) {
$estatus = '<span class="badge bg-gradient-yellow d-block">Seguimiento</span>';
}
if ($incidencia->getAtendido() == 2) {
$estatus = '<span class="badge bg-gradient-success d-block">Atendido</span>';
}
$data[] = [
'idInc' => $incidencia->getIdInc(),
'fecha' => $incidencia->getFcreacion()->format('d-m-Y'),
'dataSort' => $incidencia->getFcreacion()->format('Ymd'),
'registro' => $incidencia->getIdInc(),
'periodo' => $incidencia->getPeriodo()->getDescripcion(),
'estatus' => $estatus,
'estatusDir' => $estatusd,
'atendido' => $incidencia->getAtendido(),
'atendidoDir' => $incidencia->getAtendidoDir(),
'tema' => $incidencia->getTema()->getSiglas(),
'perfil'=> $incidencia->getPerfil(),
'descripcion'=> $incidencia->getDescripcion(),
'sugerencia'=> $incidencia->getSugerencia(),
'unidad'=> $incidencia->getUnidad()->getNombre(),
'ver' => $ver,
'editar' => $editar
];
}
return new JsonResponse($data, Response::HTTP_OK);
}
if ($nivel == 1) {
$incidencias = $this->emi->getRepository(Incidencia::class)->findBy([
'unidad' => $user->getUnidad(),
'periodo' => $perSession
]);
}
if ($nivel == 2) {
$incidencias = $this->emi->getRepository(Incidencia::class)->findBy([
'periodo' => $perSession
]);
}
if ($nivel == 3) {
$incidencias = $this->emi->getRepository(Incidencia::class)->findBy([
'unidad' => $user->getUnidad(),
'periodo' => $perSession
]);
}
return $this->render('incidencia/index.html.twig', [
'url' => $this->generateUrl('app_incidencia_index'),
'incidencias' => $incidencias,
'nivel' => $nivel,
'form' => $form->createView()
]);
}
/**
* @Route("/reporte", name= "app_incidencia_reporte", methods={"GET", "POST"})
*/
public function generarReporte(Request $request): Response
{
$perfil = $request->getSession()->get('perfilLecciones');
$nivel = $perfil[2]["nivel"];
/** @var Usuario $user */
$user = $this->getUser();
if ($nivel == 0) {
$this->addFlash('danger', 'El acceso al módulo de "Reporte PDF" está restringido.');
return $this->redirectToRoute('homepage');
}
$reporte = new \stdClass();
$reporte->finicio = null;
$reporte->ftermino = null;
$reporte->unidad = $user->getUnidad();
$form = $this->createForm(ReporteType::class, $reporte);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = [
'unidad' => $form->get('unidad')->getData(),
'finicio' => $form->get('finicio')->getData(),
'ftermino' => $form->get('ftermino')->getData(),
'correo' => $user->getCorreo(),
'nombre' => $user->getNombre() . " " . $user->getPapellido() . " " . $user->getSapellido()
];
$this->generarPDFReporteAction($data);
die();
}
if ($form->isSubmitted() && !$form->isValid()){
}
return $this->render('incidencia/reporte.html.twig', [
'form' => $form->createView(),
'nivel' => $nivel
]);
}
//#[Route('/new', name: 'app_incidencia_new', methods: ['GET', 'POST'])]
/**
* @Route("/new", name="app_incidencia_new", methods={"GET", "POST"})
*/
public function new(Request $request, EntityManagerInterface $entityManager): Response
{
$perfil = $request->getSession()->get('perfilLecciones');
$nivel = $perfil[1]["nivel"];
if ($nivel != 3) {
$this->addFlash('danger', 'El acceso a agregar "Incidencias" está restringido.');
return $this->redirectToRoute('homepage');
}
/** @var Usuario $user */
$user = $this->getUser();
date_default_timezone_set("America/Mexico_City");
$incidencium = new Incidencia();
$form = $this->createForm(IncidenciaType::class, $incidencium);
$form->remove('idInc');
$form->remove('seguimientoDir');
$form->remove('atendidoDir');
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
#identificador de incidencia
$year = date('Y');
$p1 = substr($year, 2, 2);
$unidad = $user->getUnidad();
$p2 = substr($unidad->getIdUni(), 3, 3);
$consecutivo = $unidad->getConsecutivo();
if ($consecutivo <= 999) {
$p3 = str_pad($consecutivo, 4, "0", STR_PAD_LEFT);
} else {
$p3 = '0001';
}
$unidad->setConsecutivo($consecutivo + 1);
$ident = $p1 . $p2 . $p3;
$incidencium->setIdInc($ident);
#Identificador de periodo
$periodo = $request->getSession()->get('periodoLecciones');
$periodo = $entityManager->getRepository(Periodo::class)->findOneBy(['idPrd' => $periodo->getIdPrd()]);
$incidencium->setPeriodo($periodo);
#usuario
$incidencium->setUsuario($user);
#unidad
$incidencium->setUnidad($user->getUnidad());
#fecha
$incidencium->setFcreacion(new DateTime());
$entityManager->persist($incidencium);
$entityManager->flush();
$entityManager->persist($unidad);
$entityManager->flush();
return $this->redirectToRoute('app_incidencia_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('incidencia/new.html.twig', [
'incidencium' => $incidencium,
'form' => $form,
]);
}
//#[Route('/{idInc}', name: 'app_incidencia_show', methods: ['GET'])]
/**
* @Route("/{idInc}", name= "app_incidencia_show", methods= {"GET"})
*/
public function show(Incidencia $incidencium): Response
{
return $this->render('incidencia/show.html.twig', [
'incidencium' => $incidencium,
]);
}
//#[Route('/{idInc}/edit', name: 'app_incidencia_edit', methods: ['GET', 'POST'])]
/**
* @Route("/{idInc}/edit", name= "app_incidencia_edit", methods= {"GET", "POST"})
*/
public function edit(Request $request, Incidencia $incidencium, EntityManagerInterface $entityManager): Response
{
// Periodo Actual
$a = $request->getSession()->get('periodoLecciones');
$a = $a->getIdPrd();
// Periodo de la Incidencia
$b = $incidencium->getPeriodo()->getIdPrd();
$c = true;
$form = $this->createForm(IncidenciaType::class, $incidencium);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
if ($incidencium->getAtendido() == 2) {
$estatus = "Atendido";
} elseif ($incidencium->getAtendido() == 1) {
$estatus = "Seguimiento";
} else {
$estatus = "Pendiente";
}
$data = array(
'idInc' => $incidencium->getIdInc(),
'fcreacion' => $incidencium->getFcreacion()->format('Y-m-d H:m:s'),
'perfil' => $incidencium->getPerfil(),
'tema' => $incidencium->getTema()->getSiglas(),
'descripcion' => $incidencium->getDescripcion(),
'sugerencia' => $incidencium->getSugerencia(),
'estatus' => $estatus,
'atendido' => $incidencium->getAtendido(),
'atendido_dir' => $incidencium->getAtendidoDir(),
'seguimiento' => $incidencium->getSeguimiento(),
'mensaje' => 'Se actualizo correctamente',
);
if ($incidencium->getAtendido() == 0 || $incidencium->getAtendido() == null) {
$data['atendido'] = "Pendiente";
} elseif ($incidencium->getAtendido() == 1) {
$data['atendido'] = "Seguimiento";
} else {
$data['atendido'] = "Atendido";
}
return new JsonResponse($data);
}
if($form->isSubmitted() && !$form->isValid()){
$view = $this->renderForm('incidencia/modal.html.twig', [
'incidencium' => $incidencium,
'form' => $form,
]);
$response = new JsonResponse(['form' => $view]);
$response->setStatusCode(Response::HTTP_BAD_REQUEST);
return $response;
}
if ($a != $b){
$c = false;
}
return $this->renderForm('incidencia/modal.html.twig', [
'incidencium' => $incidencium,
'form' => $form,
'actual' => $c
]);
}
//#[Route('/{idInc}', name: 'app_incidencia_delete', methods: ['POST'])]
/**
*@Route("/delete/{idInc}", name= "app_incidencia_delete", methods= {"POST"})
*/
public function delete(Request $request, Incidencia $incidencium, EntityManagerInterface $entityManager): Response
{
if ($this->isCsrfTokenValid('delete'.$incidencium->getIdInc(), $request->request->get('_token'))) {
$entityManager->remove($incidencium);
$entityManager->flush();
}
return $this->redirectToRoute('app_incidencia_index', [], Response::HTTP_SEE_OTHER);
}
private function generarPDFReporteAction($data) {
date_default_timezone_set('America/Mexico_City');
setlocale(LC_ALL, 'es_MX');
# Obtenemos el documento que se imprimirá
$formato = strftime('%d %b %Y, %H:%M hrs', strtotime(date('d-m-Y H:i')));
# Obtenemos los datos del documento
$ffinal = $data['ftermino']->format('d/m/Y');
$ftermino = $data['ftermino']->add(new DateInterval('P1D'));
$bd = $this->emi->getRepository(Incidencia::class);
$query = $bd->createQueryBuilder('i')
->where('i.unidad = :unidad AND i.fcreacion >= :inicio AND i.fcreacion <= :fin')
->setParameter('unidad', $data['unidad'])
->setParameter('inicio', $data['finicio'])
->setParameter('fin', $ftermino)
;
$consulta = $query->getQuery();
$incidencias = $consulta->getResult();
$finicial = $data['finicio']->format('d/m/Y');
$fconsulta = date('d/m/Y H:i');
$cadenaOriginal = $data['unidad'] . '||' . $data['nombre'] . '||' . $data['correo'] . '||' . $finicial . '||';
$cadenaOriginal .= $ffinal . '||' . $fconsulta;
$cadenaOriginal = str_replace(' ', '+', $cadenaOriginal);
$hash = hash('sha512', $cadenaOriginal);
$cadena64 = base64_encode($cadenaOriginal . '^' . $hash);
#Declaración de la instancia de TCPDF con el encabezado personalizado
$pdf = new DocumentoPDF();
$pdf->femision = date('d/m/Y');
$pdf->finicio = $data['finicio']->format('d/m/Y');
$pdf->ftermino = $data['ftermino']->format('d/m/Y');
$pdf->correo = $data['correo'];
$pdf->nombre = $data['nombre'];
$pdf->setPrintFooter(false);
# Información del documento
$pdf->SetCreator('Conalep Estado de México');
$pdf->SetAuthor('Registro de Incidencias');
$pdf->SetTitle('Reporte de Observaciones e Incidencias');
# Definimos los saltos de página como automáticos
#$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
#Nueva página con sus respectivas características
$pdf->AddPage('L');
$pdf->SetY(70);
# Definimos la utilización de tipigrafías
$pdf->setFontSubsetting(true);
# Declaramos una nueva tipografía para el contenido del documento
$pdf->SetFont('freesans', '', 10, '', true);
### Generamos el contenido a mostrar ###
ob_start();
$html = <<<EOD
<table width="100%" cellpadding="5" border="0">
<tr>
<td style="font-size: 12px; width: 30%">Unidad Administrativa/Plantel/Área: <strong>{$data['unidad']}</strong></td>
<td style="font-size: 12px; width: 50%; text-align: right">Periodo: </td>
<td style="font-size: 12px; width: 10%">Inicial: <strong>{$finicial}</strong></td>
<td style="font-size: 12px; width: 10%">Final: <strong>{$ffinal}</strong></td>
</tr>
</table>
<table cellpadding="5" border="0.1">
<thead>
<tr>
<td style="width: 8%; text-align: center"><strong>Folio</strong></td>
<td style="width: 8%; text-align: center"><strong>Fecha</strong></td>
<td style="width: 8%; text-align: center"><strong>Tipo</strong></td>
<td style="width: 15%; text-align: center"><strong>Sistema o actividad donde se genera</strong></td>
<td style="width: 17%; text-align: center"><strong>Perfil, rol o interesado que identifica</strong></td>
<td style="width: 17%; text-align: center"><strong>Descripción de incidente u oportunidad</strong></td>
<td style="width: 17%; text-align: center"><strong>Sugerencia de acción o recomendacion</strong></td>
<td style="width: 10%; text-align: center"><strong>Estatus</strong></td>
</tr>
</thead>
<tbody>
EOD;
$pdf->setMargins(10,75);
foreach ($incidencias as $i) {
$tipo = "";
$atendido = "";
if ($i->getTipo() == 1){
$tipo = "Observación";
} else {
$tipo = "Incidencia";
}
if ($i->getAtendido() == 0 || $i->getAtendido() == null) {
$atendido = "Pendiente";
} elseif ($i->getAtendido() == 1) {
$atendido = "Seguimiento";
} else {
$atendido = "Atendido";
}
$html .= <<<EOD
<tr>
<td style="width: 8%">{$i->getIdInc()}</td>
<td style="width: 8%">{$i->getFcreacion()->format('d/m/Y')}</td>
<td style="width: 8%">{$tipo}</td>
<td style="width: 15%; text-align: center">({$i->getTema()->getSiglas()}) {$i->getTema()->getNombre()}</td>
<td style="width: 17%; text-align: center">{$i->getPerfil()}</td>
<td style="width: 17%">{$i->getDescripcion()}</td>
<td style="width: 17%">{$i->getSugerencia()}</td>
<td style="width: 10%; text-align: center">{$atendido}</td>
</tr>
EOD;
}
$html .= <<<EOD
</tbody>
</table>
EOD;
# $pdf->write2DBarcode($cadenaOriginal, 'QRCODE,H', false, false, 20, 20, $styleQR, 'N')
$qr = new \TCPDF2DBarcode($cadenaOriginal, 'QRCODE,M');
$imgdata = $qr->getBarcodePngData(2.5, 2.5, array(0, 0, 0));
file_put_contents('assets/img/tmp/qr.png', $imgdata);
$html .=
<<<EOD
<br>
<br>
<br>
<table width="100%" cellpadding="5" border="0">
<tbody>
<tr>
<td style="font-size: 12px"><strong>ELABORÓ:</strong></td>
<td><strong>Usuario: </strong>{$data['nombre']}</td>
<td><strong>Correo: </strong>{$data['correo']}</td>
<td rowspan="3"><img src="assets/img/tmp/qr.png" alt="QRCODE" /></td>
</tr>
<tr>
<td><strong>Fecha inicio: </strong>{$finicial}</td>
<td><strong>Fecha final: </strong>{$ffinal}</td>
<td><strong>Fecha consulta: </strong>{$fconsulta}</td>
</tr>
<tr>
<td colspan="3">{$cadena64}</td>
</tr>
</tbody>
</table>
EOD;
# Imprimimos el contenido como HTML
$pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $html, $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=true);
ob_end_clean();
# ---------------------------------------------------------
# Mostramos el resultado en pantalla
$pdf->Output('ReporteIncidencias-' . date('Ymd') . '.pdf', 'D');
}
/**
* @Route("/reporte/excel", name= "app_incidencia_reporte_excel")
* @param Request $request
* @param EntityManagerInterface $entityManager
* @return BinaryFileResponse
* @throws IOException
* @throws InvalidArgumentException
* @throws WriterNotOpenedException
*/
public function generarExcelReporteAction(Request $request, EntityManagerInterface $entityManager): BinaryFileResponse
{
ini_set('memory_limit', '5120M');
ini_set('max_execution_time', 0);
ini_set('output_buffering', 0);
# Obtenemos los datos de la petición
/** @var Usuario $user */
$user = $this->getUser();
$parameters = $request->request->get('incidencia_filtro');
$periodo = $parameters['periodo'];
$tema = $parameters['tema'];
$unidad = (array_key_exists('unidad', $request->request->all()['incidencia_filtro'])) ? $parameters['unidad'] : $user->getUnidad();
# Obtenemos los datos del documento
$incidencias = $entityManager->getRepository(Incidencia::class)->filtroLecciones($periodo, $unidad, $tema);
# Definir el nombre temporal del archivo
$filePath = 'incidencias.xlsx';
# Se definen las cabeceras del archivo
$cabecera = WriterEntityFactory::createRowFromArray([
'#',
'Fecha de creacion',
'Tipo',
'Periodo',
'Usuario',
'Unidad/Plantel',
'Persona que detecta o Perfil',
'Sistema',
'Descripcion',
'Sugerencia',
'Seguimiento por Usuario',
'Estatus por Usuario',
'Seguimiento por Coordinación',
'Estatus por Coordinación',
]);
# Se crea el arreglo con los datos del cuerpo del documento
$data = [];
$n = 1;
foreach ($incidencias as $i) {
$estatus = "";
$estatusDir = "";
$tipo = "";
if ($i->getTipo() == 1){
$tipo = "Observación";
} else {
$tipo = "Incidencia";
}
if ($i->getAtendido() == 0)
$estatus = "Pendiente";
if ($i->getAtendido() == 1)
$estatus = "Seguimiento";
if ($i->getAtendido() == 2)
$estatus = "Atendido";
if ($i->getAtendidoDir() == 0)
$estatusDir = "Pendiente";
if ($i->getAtendidoDir() == 1)
$estatusDir = "Seguimiento";
if ($i->getAtendidoDir() == 2)
$estatusDir = "Atendido";
$data[] = WriterEntityFactory::createRowFromArray([
$i->getIdInc(),
$i->getFcreacion()->format('d/m/Y'),
$tipo,
$i->getPeriodo()->getDescripcion(),
$i->getUsuario()->getNombre() . ' ' . $i->getUsuario()->getPapellido() . ' - ' . $i->getUsuario()->getCorreo(),
$i->getUnidad()->getNombre(),
$i->getPerfil(),
$i->getTema()->getNombre(),
$i->getDescripcion(),
$i->getSugerencia(),
$i->getSeguimiento(),
$estatus,
$i->getSeguimientoDir(),
$estatusDir,
]);
$n++;
}
# Se crea el documento en formato CSV
$writer = WriterEntityFactory::createXLSXWriter();
$writer
->openToFile($filePath)
->addRow($cabecera)
->addRows($data)
->close()
;
$response = new BinaryFileResponse($filePath);
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
'ReporteIncidencias' . '_' . date('Y-m-d') . '.xlsx'
);
$response->deleteFileAfterSend(true);
return $response;
}
}