<?php
namespace App\Controller;
use App\Entity\Embajadores;
use App\Entity\Nominapago;
use App\Entity\Agenda;
use App\Entity\ColegioParticipante;
use App\Entity\Dependencia;
use App\Entity\EmbajadorParticipante;
use App\Form\EmbajadorParticipanteType;
use App\Form\EmbajadorParticipanteeditType;
use App\Form\EditarMontoPagoType;
use App\Service\Mensajes;
use App\Form\EmbajadorParticipante2Type;
use App\Form\EmbajadorParticipanterolType;
use App\Repository\EmbajadorParticipanteRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Routing\Annotation\Route;
use App\Service\QRConfirmacionService;
use App\Service\CapacidadService;
/**
* @Route("/embajador/participante")
*/
class EmbajadorParticipanteController extends AbstractController
{
/**
* @Route("/", name="app_embajador_participante_index", methods={"GET"})
*/
public function index(EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
return $this->render('embajador_participante/index.html.twig', [
'embajador_participantes' => $embajadorParticipanteRepository->findAll(),
]);
}
/**
* @Route("/pagadas", name="app_embajador_participante_pagadas", methods={"GET"})
*/
public function pagadas(EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
$entityManager = $this->getDoctrine()->getManager();
$nominas = $entityManager->getRepository(Nominapago::class)->findAll();
return $this->render('embajador_participante/pagadas.html.twig', [
'embajador_participantes' => $embajadorParticipanteRepository->findByNomina($nominas),
]);
}
/**
* @Route("/agregar", name="app_embajador_participante_new", methods={"GET", "POST"})
*/
public function agregar( Request $request, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
$entityManager = $this->getDoctrine()->getManager();
$embajadorParticipante = new EmbajadorParticipante();
$form = $this->createForm(EmbajadorParticipante2Type::class, $embajadorParticipante);
$form->handleRequest($request);
$hoy = new \DateTime('now');
if ($form->isSubmitted() && $form->isValid()) {
$embajadorParticipante->setEstado("seleccionado");
$embajadorParticipante->setFecha($hoy);
$embajadorParticipante->setTipo("regular");
$embajadorParticipanteRepository->add($embajadorParticipante, true);
return $this->redirectToRoute('app_embajador_participante_pagos');
}
return $this->renderForm('embajador_participante/nuevo.html.twig', [
'form' => $form,
]);
}
/**
* @Route("/postularrol/{id}", name="app_embajador_participante_newrol", methods={"GET", "POST"})
*/
public function postularrol($id, Request $request, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
$user = $this->getUser();
$entityManager = $this->getDoctrine()->getManager();
$embajadorParticipante = new EmbajadorParticipante();
$agenda = $entityManager->getRepository(Agenda::class)->findOneById($id);
$embajador = $entityManager->getRepository(Embajadores::class)->findOneBy(['correo' => $user->getUserIdentifier()]);
if (!$embajador || strtolower(trim($embajador->getEstado() ?? '')) === 'no vigente') {
return $this->redirectToRoute('agenda_index_estudiante');
}
$entityManager = $this->getDoctrine()->getManager();
$cadena = $agenda->getRoles();
// Parsear roles en formato "rol:monto,rol:monto"
$rolesArray = explode(',', $cadena);
$opciones = [];
$rolesConMontos = []; // Array para pasar a la vista con formato legible
foreach ($rolesArray as $rolCompleto) {
$partes = explode(':', trim($rolCompleto));
if (!empty($partes[0])) {
$nombreRol = trim($partes[0]);
$monto = isset($partes[1]) ? intval(trim($partes[1])) : 0;
$opciones[] = $nombreRol;
$rolesConMontos[] = [
'nombre' => $nombreRol,
'monto' => $monto
];
}
}
$opciones = array_combine($opciones, $opciones);
$embajadorParticipante = new EmbajadorParticipante();
$form = $this->createForm(EmbajadorParticipanterolType::class, $embajadorParticipante, [
'opciones' => $opciones,
]);
$form->handleRequest($request);
$hoy = new \DateTime('now');
if ($form->isSubmitted() && $form->isValid()) {
$embajadorParticipante->setEstado("pendiente seleccion");
$embajadorParticipante->setFecha($hoy);
$embajadorParticipante->setAgenda($agenda);
$embajadorParticipante->setEmbajadores($embajador);
// Asignar monto según el rol seleccionado
$rolSeleccionado = $embajadorParticipante->getRol();
if ($rolSeleccionado && $agenda->getRoles()) {
$rolesArray = explode(',', $agenda->getRoles());
foreach ($rolesArray as $rolCompleto) {
$partes = explode(':', trim($rolCompleto));
if (count($partes) >= 2 && trim($partes[0]) === $rolSeleccionado) {
$embajadorParticipante->setMonto(intval(trim($partes[1])));
break;
}
}
}
$embajadorParticipanteRepository->add($embajadorParticipante, true);
return $this->redirectToRoute('agenda_index_estudiante');
}
return $this->renderForm('embajador_participante/nuevorol.html.twig', [
'form' => $form,
'agenda' => $agenda,
'rolesConMontos' => $rolesConMontos,
]);
}
/**
* @Route("/new/{id}", name="app_embajador_participante_newbyagenda", methods={"GET", "POST"})
*/
public function new($id, Request $request, EmbajadorParticipanteRepository $embajadorParticipanteRepository, QRConfirmacionService $qrService, CapacidadService $capacidadService): Response
{
$entityManager = $this->getDoctrine()->getManager();
$embajadorParticipante = new EmbajadorParticipante();
$agenda = $entityManager->getRepository(Agenda::class)->findOneById($id);
// Parsear roles de la agenda para el formulario
$rolesOpciones = [];
if ($agenda->getRoles()) {
$rolesArray = explode(',', $agenda->getRoles());
foreach ($rolesArray as $rolCompleto) {
$partes = explode(':', trim($rolCompleto));
if (!empty($partes[0])) {
$nombreRol = trim($partes[0]);
$monto = isset($partes[1]) ? intval(trim($partes[1])) : 0;
// Formato: "Nombre del Rol ($monto)" => "Nombre del Rol"
$rolesOpciones[$nombreRol . ' ($' . number_format($monto, 0, ',', '.') . ')'] = $nombreRol;
}
}
}
$form = $this->createForm(EmbajadorParticipanteType::class, $embajadorParticipante, [
'roles_opciones' => $rolesOpciones
]);
$form->handleRequest($request);
$colegios = $entityManager->getRepository(ColegioParticipante::class)->findByAgenda($agenda->getId());
$embajadores = $entityManager->getRepository(EmbajadorParticipante::class)->findByAgenda($agenda->getId());
// dependencias + optional filter
$dependencias = $entityManager->getRepository(Dependencia::class)->findAll();
$selectedDep = $request->query->getInt('dependencia') ?: null;
if ($selectedDep) {
$colegios = array_values(array_filter($colegios, function($cp) use ($selectedDep) {
$col = $cp->getColegio();
return $col && $col->getDependencia() && $col->getDependencia()->getId() == $selectedDep;
}));
}
// Obtener todos los embajadores para el autocomplete
$todosEmbajadores = $entityManager->getRepository(Embajadores::class)->findAll();
$embajadoresJson = [];
foreach ($todosEmbajadores as $emb) {
$embajadoresJson[] = [
'id' => $emb->getId(),
'nombre' => $emb->getNombre(),
'rut' => $emb->getRut(),
'correo' => $emb->getCorreo(),
'carrera'=> $emb->getCarrera(),
];
}
if ($form->isSubmitted() && $form->isValid()) {
// VALIDAR QUE EL EMBAJADOR NO ESTÉ YA AGREGADO A ESTA AGENDA
$embajadorSeleccionado = $embajadorParticipante->getEmbajadores();
$yaExiste = $embajadorParticipanteRepository->findOneBy([
'agenda' => $agenda,
'embajadores' => $embajadorSeleccionado
]);
if ($yaExiste) {
$this->addFlash('error', 'El embajador ' . $embajadorSeleccionado->getNombre() . ' ya está agregado a esta agenda.');
return $this->redirectToRoute('app_embajador_participante_newbyagenda', array('id' => $agenda->getId()));
}
$embajadorParticipante->setAgenda($agenda);
$embajadorParticipante->setEstado("postulante"); // Cambiado de "seleccionado" a "postulante"
$embajadorParticipante->setTipo("regular");
$embajadorParticipante->setFecha(new \DateTime('now'));
// Asignar monto según el rol seleccionado
$rolSeleccionado = $embajadorParticipante->getRol();
if ($rolSeleccionado && $agenda->getRoles()) {
$rolesArray = explode(',', $agenda->getRoles());
foreach ($rolesArray as $rolCompleto) {
$partes = explode(':', trim($rolCompleto));
if (count($partes) >= 2 && trim($partes[0]) === $rolSeleccionado) {
$embajadorParticipante->setMonto(intval(trim($partes[1])));
break;
}
}
}
// VALIDAR CAPACIDAD ANTES DE ASIGNAR
if ($agenda->getCapacidadMaxima() && !$capacidadService->hayCapacidadDisponible($agenda, 1)) {
$this->addFlash('error', 'El evento "' . $agenda->getTitulo() . '" ha alcanzado su capacidad máxima. No se puede agregar más embajadores.');
return $this->redirectToRoute('app_embajador_participante_newbyagenda', array('id' => $agenda->getId()));
}
$embajadorParticipanteRepository->add($embajadorParticipante, true);
// Generar código QR para el embajador participante
$qrService->asignarCodigoQR($embajadorParticipante);
// INCREMENTAR CONTADOR DE CAPACIDAD
if ($agenda->getCapacidadMaxima()) {
$capacidadService->registrarInscripcion($agenda, 1);
}
$entityManager->flush();
$this->addFlash('success', 'Embajador agregado exitosamente como postulante.');
return $this->redirectToRoute('app_embajador_participante_newbyagenda', array('id' => $agenda->getId()));
}
$hoy = new \DateTime('now');
$desde = new \DateTime('now');
$hasta = $hoy->modify('+7 days');
$anioInicio = new \DateTime((new \DateTime())->format('Y') . '-01-01 00:00:00');
$anioFin = new \DateTime((new \DateTime())->format('Y') . '-12-31 23:59:59');
return $this->renderForm('embajador_participante/new.html.twig', [
'embajador_participante' => $embajadorParticipante,
'form' => $form,
'colegio_participantes' => $colegios,
'colegios' => $colegios,
'agenda'=>$agenda,
'embajadores'=>$embajadores,
'embajadores_json' => json_encode($embajadoresJson),
'desde' => $desde,
'hasta' => $hasta,
'anio_inicio' => $anioInicio,
'anio_fin' => $anioFin,
'dependencias' => $dependencias,
'selected_dependencia' => $selectedDep,
]);
}
/**
* @Route("/export-postulantes/{id}", name="app_embajador_participante_export_postulantes", methods={"GET"})
*/
public function exportPostulantes($id): Response
{
$entityManager = $this->getDoctrine()->getManager();
$agenda = $entityManager->getRepository(Agenda::class)->findOneById($id);
if (!$agenda) {
throw $this->createNotFoundException('Agenda no encontrada');
}
// Obtener todos los postulantes
$embajadores = $entityManager->getRepository(EmbajadorParticipante::class)->findByAgenda($agenda->getId());
// Filtrar solo pendientes y rechazados
$postulantes = array_filter($embajadores, function($embajador) {
return $embajador->getEstado() == "pendiente seleccion" || $embajador->getEstado() == "rechazado";
});
// Crear el Excel
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// Configurar encabezados
$sheet->setTitle('Postulantes');
$sheet->setCellValue('A1', 'Nombre');
$sheet->setCellValue('B1', 'RUT');
$sheet->setCellValue('C1', 'Correo');
$sheet->setCellValue('D1', 'Carrera');
$sheet->setCellValue('E1', 'Estado Embajador');
$sheet->setCellValue('F1', 'Tags');
$sheet->setCellValue('G1', 'Rol Postulado');
$sheet->setCellValue('H1', 'Estado Postulación');
$sheet->setCellValue('I1', 'Celular');
// Estilo para encabezados
$headerStyle = [
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => '4472C4']],
'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
];
$sheet->getStyle('A1:I1')->applyFromArray($headerStyle);
// Llenar datos
$row = 2;
foreach ($postulantes as $embajadorParticipante) {
$embajador = $embajadorParticipante->getEmbajadores();
// Tags
$tags = [];
foreach ($embajador->getTags() as $tag) {
$tags[] = $tag->getNombre();
}
$tagsStr = implode(', ', $tags);
$sheet->setCellValue('A' . $row, $embajador->getNombre());
$sheet->setCellValue('B' . $row, $embajador->getRut());
$sheet->setCellValue('C' . $row, $embajador->getCorreo());
$sheet->setCellValue('D' . $row, $embajador->getCarrera());
$sheet->setCellValue('E' . $row, $embajador->getEstado());
$sheet->setCellValue('F' . $row, $tagsStr);
$sheet->setCellValue('G' . $row, $embajadorParticipante->getRol());
$sheet->setCellValue('H' . $row, $embajadorParticipante->getEstado());
$sheet->setCellValue('I' . $row, $embajador->getCelular());
$row++;
}
// Auto-ajustar ancho de columnas
foreach (range('A', 'I') as $col) {
$sheet->getColumnDimension($col)->setAutoSize(true);
}
// Crear el archivo Excel
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$fileName = 'Postulantes_' . $agenda->getId() . '_' . date('Y-m-d') . '.xlsx';
// Crear respuesta con el archivo
$temp_file = tempnam(sys_get_temp_dir(), $fileName);
$writer->save($temp_file);
return $this->file($temp_file, $fileName, ResponseHeaderBag::DISPOSITION_INLINE);
}
/**
* @Route("/export-anual/{anio}", name="app_embajador_participante_export_anual", methods={"GET"})
*/
public function exportAnual(int $anio): Response
{
$em = $this->getDoctrine()->getManager();
$inicio = new \DateTime($anio . '-01-01');
$fin = new \DateTime($anio . '-12-31');
$participantes = $em->createQueryBuilder()
->select('ep')
->from(EmbajadorParticipante::class, 'ep')
->join('ep.agenda', 'a')
->join('ep.embajadores', 'e')
->where('a.fecha BETWEEN :inicio AND :fin')
->andWhere('ep.estado IN (:estados)')
->setParameter('inicio', $inicio)
->setParameter('fin', $fin)
->setParameter('estados', ['Confirmado', 'Realizado', 'En pago'])
->orderBy('e.nombre', 'ASC')
->getQuery()
->getResult();
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle('Participaciones ' . $anio);
// Encabezados
$headers = ['Nombre', 'RUT', 'Correo', 'Carrera', 'Fecha Actividad', 'Lugar', 'Tipo Actividad', 'Rol', 'Monto', 'Estado Pago'];
foreach ($headers as $i => $h) {
$sheet->setCellValueByColumnAndRow($i + 1, 1, $h);
}
$headerStyle = [
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => '4472C4']],
'alignment' => ['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
];
$sheet->getStyle('A1:J1')->applyFromArray($headerStyle);
// Datos
$row = 2;
foreach ($participantes as $ep) {
$emb = $ep->getEmbajadores();
$agenda = $ep->getAgenda();
$tipo = $agenda && $agenda->getTipoAgenda() ? $agenda->getTipoAgenda()->getNombre() : '';
$fecha = $agenda && $agenda->getFecha() ? $agenda->getFecha()->format('d-m-Y') : '';
$lugar = $agenda ? $agenda->getLugar() : '';
$sheet->setCellValueByColumnAndRow(1, $row, $emb ? $emb->getNombre() : '');
$sheet->setCellValueByColumnAndRow(2, $row, $emb ? $emb->getRut() : '');
$sheet->setCellValueByColumnAndRow(3, $row, $emb ? $emb->getCorreo() : '');
$sheet->setCellValueByColumnAndRow(4, $row, $emb ? $emb->getCarrera(): '');
$sheet->setCellValueByColumnAndRow(5, $row, $fecha);
$sheet->setCellValueByColumnAndRow(6, $row, $lugar);
$sheet->setCellValueByColumnAndRow(7, $row, $tipo);
$sheet->setCellValueByColumnAndRow(8, $row, $ep->getRol());
$sheet->setCellValueByColumnAndRow(9, $row, $ep->getMonto());
$sheet->setCellValueByColumnAndRow(10, $row, $ep->getPagado() ? 'Pagado' : 'Pendiente');
$row++;
}
foreach (range(1, 10) as $col) {
$sheet->getColumnDimensionByColumn($col)->setAutoSize(true);
}
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$fileName = 'Participacion_Embajadores_' . $anio . '.xlsx';
$tmpFile = tempnam(sys_get_temp_dir(), 'emb_');
$writer->save($tmpFile);
return $this->file($tmpFile, $fileName, ResponseHeaderBag::DISPOSITION_ATTACHMENT);
}
/**
* @Route("/{id}", name="app_embajador_participante_show", methods={"GET"}, requirements={"id"="\d+"})
*/
public function show(EmbajadorParticipante $embajadorParticipante): Response
{
return $this->render('embajador_participante/show.html.twig', [
'embajador_participante' => $embajadorParticipante,
]);
}
/**
* @Route("/{id}/edit", name="app_embajador_participante_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, EmbajadorParticipante $embajadorParticipante, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
$cadena = $embajadorParticipante->getAgenda()->getRoles();
// Parsear roles en formato "rol:monto,rol:monto"
$rolesArray = explode(',', $cadena);
$opciones = [];
foreach ($rolesArray as $rolCompleto) {
$partes = explode(':', trim($rolCompleto));
if (!empty($partes[0])) {
$nombreRol = trim($partes[0]);
$opciones[] = $nombreRol;
}
}
$opciones = array_combine($opciones, $opciones);
$msj2 = "Has sido seleccionado para la actividad ".$embajadorParticipante->getAgenda()->getTipoAgenda()->getNombre().", el día ".date_format($embajadorParticipante->getAgenda()->getFecha(),"d/m/Y").", en ".$embajadorParticipante->getAgenda()->getLugar();
$msj = "Hola,<br><br>
Has sido seleccionado para la actividad <strong>".$embajadorParticipante->getAgenda()->getTipoAgenda()->getNombre()."</strong>, el día <strong>".date_format($embajadorParticipante->getAgenda()->getFecha(),"d/m/Y")."</strong>, en <strong>".$embajadorParticipante->getAgenda()->getLugar()."</strong> con el rol: <strong>".$embajadorParticipante->getRol()."</strong><br><br>
".$embajadorParticipante->getAgenda()->getTipoAgenda()->getCuerpo()."<br><br>
Para más detalles de la actividad puedes revisar la plataforma Delfy.<br><br>
Saludos cordiales";
// $embajadorParticipante->setCorreo($msj);
// El monto ahora se asigna según el rol seleccionado (está en roles como "rol:monto")
// Si no tiene monto, se deja null o se asigna después según el rol
// Crear mapa de roles con montos para JavaScript
$rolesConMontos = [];
$rolesArray = explode(',', $cadena);
foreach ($rolesArray as $rolCompleto) {
$partes = explode(':', trim($rolCompleto));
if (count($partes) >= 2) {
$nombreRol = trim($partes[0]);
$monto = intval(trim($partes[1]));
$rolesConMontos[$nombreRol] = $monto;
}
}
$form = $this->createForm(EmbajadorParticipanteeditType::class, $embajadorParticipante, [
'opciones' => array_combine($opciones, $opciones),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$embajadorParticipante->setEstado("seleccionado");
$embajadorParticipante->setTipo("regular");
// Asignar monto según el rol seleccionado si no tiene monto
$rolSeleccionado = $embajadorParticipante->getRol();
if ($rolSeleccionado && $embajadorParticipante->getAgenda()->getRoles()) {
$rolesArray = explode(',', $embajadorParticipante->getAgenda()->getRoles());
foreach ($rolesArray as $rolCompleto) {
$partes = explode(':', trim($rolCompleto));
if (count($partes) >= 2 && trim($partes[0]) === $rolSeleccionado) {
// Solo actualizar si no tiene monto o si es diferente
if (!$embajadorParticipante->getMonto()) {
$embajadorParticipante->setMonto(intval(trim($partes[1])));
}
break;
}
}
}
$embajadorParticipanteRepository->add($embajadorParticipante, true);
// Detectar qué botón se presionó
$action = $request->request->get('action');
if ($action === 'save_and_send') {
// Redirigir a la página de envío de correo
return $this->redirectToRoute('app_embajador_participante_correo', ['id' => $embajadorParticipante->getId()]);
} else {
// Solo guardar, redirigir a la lista de embajadores
$this->addFlash('success', 'Embajador seleccionado correctamente (sin envío de correo)');
return $this->redirectToRoute('app_embajador_participante_newbyagenda', ['id' => $embajadorParticipante->getAgenda()->getId()]);
}
}
return $this->renderForm('embajador_participante/edit.html.twig', [
'embajador_participante' => $embajadorParticipante,
'form' => $form,
'msj2' => $msj2,
'roles_montos_json' => json_encode($rolesConMontos),
]);
}
/**
* @Route("/borrar/{id}", name="app_embajador_participante_delete", methods={"GET", "POST"})
*/
public function delete(Request $request, EmbajadorParticipante $embajadorParticipante, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
if ($this->isGranted('ROLE_ADMIN')) {
$id = $embajadorParticipante->getAgenda()->getId();
//if ($this->isCsrfTokenValid('delete'.$embajadorParticipante->getId(), $request->request->get('_token'))) {
$embajadorParticipanteRepository->remove($embajadorParticipante, true);
//}
return $this->redirectToRoute('app_embajador_participante_newbyagenda', array('id' => $id));
}
}
/**
* @Route("/postular/{id}", name="app_embajador_participante_postular", methods={"GET", "POST"})
*/
public function postular($id, Request $request, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
$user = $this->getUser();
$entityManager = $this->getDoctrine()->getManager();
$embajadorParticipante = new EmbajadorParticipante();
$agenda = $entityManager->getRepository(Agenda::class)->findOneById($id);
$embajador = $entityManager->getRepository(Embajadores::class)->findOneBy(['correo' => $user->getUserIdentifier()]);
if (!$embajador || strtolower(trim($embajador->getEstado() ?? '')) === 'no vigente') {
return $this->redirectToRoute('agenda_index_estudiante');
}
$embajadorparticipante = $entityManager->getRepository(EmbajadorParticipante::class)->findOneBy(array('agenda'=>$agenda, 'embajadores'=>$embajador));
if($embajadorparticipante){
return $this->redirectToRoute('agenda_index_estudiante');
}
$embajadorParticipante->setAgenda($agenda);
$embajadorParticipante->setEmbajadores($embajador);
// El monto ahora se obtiene del rol seleccionado (formato "rol:monto" en agenda->roles)
// Se asignará después cuando se seleccione el rol específico
$embajadorParticipante->setEstado("pendiente seleccion");
$embajadorParticipanteRepository->add($embajadorParticipante, true);
return $this->redirectToRoute('agenda_index_estudiante');
}
/**
* @Route("/cambioestado/{id}/{estado}", name="app_embajador_participante_estado", methods={"GET", "POST"})
*/
public function cancelar($estado, Request $request, EmbajadorParticipante $embajadorParticipante, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
if ($this->isGranted('ROLE_ADMIN')) {
$id = $embajadorParticipante->getAgenda()->getId();
$embajadorParticipante->setEstado($estado);
$embajadorParticipante->setTipo(null);
$embajadorParticipanteRepository->add($embajadorParticipante, true);
return $this->redirectToRoute('app_embajador_participante_newbyagenda', array('id' => $id));
}
}
/**
* @Route("rechazar/{id}/{estado}", name="app_embajador_participante_rechazar", methods={"GET", "POST"})
*/
public function rechazar($estado, Request $request, EmbajadorParticipante $embajadorParticipante, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
if ($this->isGranted('ROLE_ADMIN')) {
$id2 = $embajadorParticipante->getEmbajadores()->getId();
$embajadorParticipante->setEstado($estado);
$embajadorParticipante->setTipo(null);
$embajadorParticipante->setNomina(null);
$embajadorParticipanteRepository->add($embajadorParticipante, true);
return $this->redirectToRoute('app_embajador_participante_pagar', array( 'id' => $id2));
}
}
/**
* @Route("sacardepago/{id}/", name="app_embajador_participante_quitarnomina", methods={"GET", "POST"})
*/
public function sacardepago( Request $request, EmbajadorParticipante $embajadorParticipante, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
if ($this->isGranted('ROLE_ADMIN')) {
$id2 = $embajadorParticipante->getEmbajadores()->getId();
$embajadorParticipante->setEstado("seleccionado");
$embajadorParticipante->setNomina(null);
$embajadorParticipanteRepository->add($embajadorParticipante, true);
return $this->redirectToRoute('app_embajador_participante_pagar', array( 'id' => $id2));
}
}
/**
* @Route("agregarpago/{pago}/{id}", name="app_embajador_participante_agregarpago", methods={"GET", "POST"})
*/
public function agregarpago($id, $pago): Response
{
$entityManager = $this->getDoctrine()->getManager();
$nomina = $entityManager->getRepository(Nominapago::class)->findOneById($pago);
$embajadorParticipante = $entityManager->getRepository(EmbajadorParticipante::class)->findOneById($id);
if ($this->isGranted('ROLE_ADMIN')) {
$id2 = $embajadorParticipante->getEmbajadores()->getId();
$embajadorParticipante->setNomina($nomina);
$embajadorParticipante->setEstado("En pago");
$entityManager->flush();
return $this->redirectToRoute('app_embajador_participante_pagar', array( 'id' => $id2));
}
}
/**
* @Route("/pagos", name="app_embajador_participante_pagos", methods={"GET"})
*/
public function pagos(EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
$qbx = $this->getDoctrine()->getManager()->createQueryBuilder()
->select('count(ep) as cantidad, sum(ep.monto) as monto, em.nombre as nombre, em.id as id, em.rut as rut, em.correo as correo, em.carrera as carrera')
->from(EmbajadorParticipante::class, 'ep')
->leftJoin(Embajadores::class, 'em', 'WITH', 'ep.embajadores = em.id')
->leftJoin(Agenda::class, 'a', 'WITH', 'ep.agenda = a.id')
->andWhere('a.estadoAgenda = :estadoa or ep.agenda is null')
->andWhere('ep.estado = :estado')
->andWhere('ep.tipo != :tipo')
->setParameter('estado', "seleccionado")
->setParameter('estadoa', "2")
->setParameter('tipo', "tp")
->groupBy('em.id')
;
$embajadores = $qbx->getQuery()->getResult();
return $this->render('embajador_participante/pagos.html.twig', [
'embajador_participantes' => $embajadores,
]);
}
/**
* @Route("/pagar/{id}", name="app_embajador_participante_pagar", methods={"GET", "POST"})
*/
public function pagar($id, EmbajadorParticipanteRepository $embajadorParticipanteRepository, Request $request): Response
{
$qbx = $this->getDoctrine()->getManager()->createQueryBuilder()
->select('ep')
->from(EmbajadorParticipante::class, 'ep')
->leftJoin(Embajadores::class, 'em', 'WITH', 'ep.embajadores = em.id')
->leftJoin(Agenda::class, 'a', 'WITH', 'ep.agenda = a.id')
->andWhere('ep.estado = :estado')
->andWhere('em.id = :id')
->andWhere('em.id = :id')
->andWhere('a.estadoAgenda = :estadoa or ep.agenda is null')
->setParameter('estado', "seleccionado")
->setParameter('estadoa', "2")
->setParameter('id', $id)
;
$embajadores = $qbx->getQuery()->getResult();
$pagos = $this->getDoctrine()->getManager()->createQueryBuilder()
->select('n')
->from(Nominapago::class, 'n')
->leftJoin(Embajadores::class, 'em', 'WITH', 'n.embajador = em.id')
->andWhere('em.id = :id')
->andWhere('n.estado IN (:estados)')
->setParameter('id', $id)
->setParameter('estados', ['pendiente', 'Emitida'])
->getQuery()
->getResult()
;
$nominas = $this->getDoctrine()->getManager()->createQueryBuilder()
->select('n')
->from(Nominapago::class, 'n')
->leftJoin(Embajadores::class, 'em', 'WITH', 'n.embajador = em.id')
->andWhere('em.id = :id')
->setParameter('id', $id)
->orderBy('n.id', 'DESC')
->getQuery()
->getResult()
;
$form = $this->createForm(EditarMontoPagoType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$id_embajador_participante = $form->get('id')->getData();
$entityManager = $this->getDoctrine()->getManager();
$embajador_participante = $entityManager->getRepository(EmbajadorParticipante::class)->findOneById($id_embajador_participante);
$monto = $form->get('monto')->getData();
$embajador_participante->setMonto($monto);
$observacion = $form->get('observacion')->getData();
$embajador_participante->setObservacion($observacion);
$entityManager->persist($embajador_participante);
$entityManager->persist($embajador_participante);
$entityManager->flush();
return $this->redirectToRoute('app_embajador_participante_pagar', array('id' => $id));
}
return $this->render('embajador_participante/pagar.html.twig', [
'embajador_participantes' => $embajadores,
'id' => $id,
'pagos' => $pagos,
'nominas' => $nominas,
'form' => $form->createView(),
]);
}
/**
* @Route("pagosbyuser/{id}", name="app_embajador_participante_pagosbyuser", methods={"GET"})
*/
public function pagosbyuser($id, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
$entityManager = $this->getDoctrine()->getManager();
$embajador = $entityManager->getRepository(Embajadores::class)->findOneById($id);
$actividades = $embajadorParticipanteRepository->findBy(array('embajadores'=>$embajador, 'pagado'=>0));
return $this->render('embajador_participante/pagosbyuser.html.twig', [
'embajador_participantes' => $actividades,
]);
}
/**
* @Route("/pagos2", name="app_embajador_participante_pagos2", methods={"GET", "POST"})
*/
public function pagos2(Request $request, EmbajadorParticipanteRepository $embajadorParticipanteRepository, \App\Service\Mensajes $mensajes): Response
{
$entityManager = $this->getDoctrine()->getManager();
// Obtener todas las agendas para el selector
$agendas = $entityManager->getRepository(Agenda::class)
->createQueryBuilder('a')
->orderBy('a.fecha', 'DESC')
->getQuery()
->getResult();
$embajadoresData = [];
$agendaSeleccionada = null;
// Si se seleccionó una agenda
if ($request->isMethod('POST') && $request->request->has('agenda_id') && !$request->request->has('generar_nominas')) {
$agendaId = $request->request->get('agenda_id');
$agendaSeleccionada = $entityManager->getRepository(Agenda::class)->find($agendaId);
if ($agendaSeleccionada) {
// Obtener embajadores de esa agenda que no están pagados
// Solo incluir estado: Realizado (evento ya ejecutado)
$embajadoresData = $entityManager->getRepository(EmbajadorParticipante::class)
->createQueryBuilder('ep')
->leftJoin('ep.embajadores', 'e')
->where('ep.agenda = :agenda')
->andWhere('ep.pagado = 0 OR ep.pagado IS NULL')
->andWhere('ep.estado = :estadoRealizado')
->andWhere('e.id IS NOT NULL')
->setParameter('agenda', $agendaSeleccionada)
->setParameter('estadoRealizado', 'Realizado')
->orderBy('e.nombre', 'ASC')
->getQuery()
->getResult();
}
}
// Si se está generando nóminas masivas
if ($request->isMethod('POST') && $request->request->has('generar_nominas')) {
$seleccionados = $request->request->all('embajador');
$montos = $request->request->all('monto');
$enviarCorreos = $request->request->get('enviar_correos', false);
if (empty($seleccionados)) {
$this->addFlash('error', 'Debe seleccionar al menos un embajador');
return $this->redirectToRoute('app_embajador_participante_pagos2');
}
$nominasCreadas = 0;
$correosEnviados = 0;
// Agrupar por embajador
$embajadoresPorPersona = [];
foreach ($seleccionados as $embajadorParticipanteId) {
$embajadorPart = $embajadorParticipanteRepository->find($embajadorParticipanteId);
if ($embajadorPart && $embajadorPart->getEmbajadores()) {
$embajadorId = $embajadorPart->getEmbajadores()->getId();
if (!isset($embajadoresPorPersona[$embajadorId])) {
$embajadoresPorPersona[$embajadorId] = [
'embajador' => $embajadorPart->getEmbajadores(),
'actividades' => []
];
}
$embajadoresPorPersona[$embajadorId]['actividades'][] = [
'participante' => $embajadorPart,
'monto' => isset($montos[$embajadorParticipanteId]) ? (float)$montos[$embajadorParticipanteId] : 0
];
}
}
// Crear una nómina por cada embajador
foreach ($embajadoresPorPersona as $datos) {
$embajador = $datos['embajador'];
$actividades = $datos['actividades'];
// Crear nómina
$nominapago = new Nominapago();
$nominapago->setFecha(new \DateTime());
$nominapago->setEstado('pendiente');
$nominapago->setEmbajador($embajador);
$nominapago->setEnviado(0);
$entityManager->persist($nominapago);
$montoTotal = 0;
// Asignar actividades a la nómina
foreach ($actividades as $actividadData) {
$participante = $actividadData['participante'];
$monto = $actividadData['monto'];
$participante->setMonto($monto);
$participante->setNomina($nominapago);
$participante->setEstado('En pago');
$entityManager->persist($participante);
$montoTotal += $monto;
}
$entityManager->flush();
$nominasCreadas++;
// Enviar correo si está marcado
if ($enviarCorreos && $montoTotal > 0) {
try {
$this->enviarCorreoSolicitudBoleta($nominapago, $montoTotal, $mensajes);
$nominapago->setEnviado(1);
// $nominapago->setFechaEnvio(new \DateTime()); // Deshabilitado - columna no existe en producción
$nominapago->setEstado('Emitida');
$entityManager->flush();
$correosEnviados++;
} catch (\Exception $e) {
// Log error pero continuar
}
}
}
$mensaje = "Se crearon {$nominasCreadas} nómina(s) exitosamente.";
if ($enviarCorreos) {
$mensaje .= " Se enviaron {$correosEnviados} correo(s) de solicitud de boleta.";
}
$this->addFlash('success', $mensaje);
return $this->redirectToRoute('app_nominapago_index');
}
return $this->render('embajador_participante/pagos2.html.twig', [
'agendas' => $agendas,
'agenda_seleccionada' => $agendaSeleccionada,
'embajadores' => $embajadoresData,
]);
}
/**
* Enviar correo de solicitud de boleta
*/
private function enviarCorreoSolicitudBoleta(Nominapago $nominapago, float $monto, \App\Service\Mensajes $mensajes): void
{
// Intentar usar plantilla de base de datos
$plantillaCorreo = $this->container->get(PlantillaCorreoService::class);
$variables = [
'nombre' => $nominapago->getEmbajador()->getNombre(),
'monto' => number_format($monto, 0, ',', '.'),
'razon_social' => 'Pontificia Universidad Católica de Chile',
'rut' => '81.698.900-0',
'direccion' => 'Avda. Libertador Bernardo O\'Higgins N 340, Santiago',
];
try {
$correoData = $plantillaCorreo->procesarPlantilla('solicitud_boleta', $variables);
if ($correoData) {
// Usar plantilla de la base de datos
$asunto = $correoData['asunto'];
$mensaje = $correoData['cuerpo'];
} else {
// Fallback al mensaje básico
$asunto = 'Solicitud de Boleta - Pago Embajador';
$mensaje = 'Estimado/a ' . $nominapago->getEmbajador()->getNombre() . ',
Junto con saludar y esperando te encuentres muy bien, te escribimos para solicitar la boleta de los trabajos realizados. Para poder dar inicio al procesamiento de tu pago, necesitamos que subas la boleta en formato PDF al sistema Delfy.
A continuación, te dejamos los datos con los que debes completar la boleta en el sitio del SII:
Razón Social: Pontificia Universidad Católica de Chile
RUT: 81.698.900-0
Dirección: Avda. Libertador Bernardo O\'Higgins N 340, Santiago
Monto: $' . number_format($monto, 0, ',', '.') . '
Una vez que inicies sesión con tu usuario en Delfy, debes buscar en el menú lateral la pestaña "Boletas y pagos" y ahí seleccionar la opción de boletas pendientes por subir.
Para que podamos procesarlo es necesario que el documento que subas a Delfy esté en formato PDF, el que puedes descargar directamente desde el sitio del SII al generar tu boleta. Además, el nombre del archivo debe seguir el siguiente formato "Nombre Completo – N° Boleta" (Por ejemplo "Vivian Avalos – 150")
Saludos cordiales,
Equipo de Difusión UC';
}
$mensajes->enviar5Mensaje(
$nominapago->getEmbajador()->getCorreo(),
'vivian.avalos@uc.cl',
$asunto,
$mensaje
);
} catch (\Exception $e) {
// Si falla, usar mensaje básico
$asunto = 'Solicitud de Boleta - Pago Embajador';
$cuerpo = 'Estimado/a ' . $nominapago->getEmbajador()->getNombre() . ',
Junto con saludar, te informamos que se ha generado una nómina de pago por un total de $' . number_format($monto, 0, ',', '.') . '.
Para procesar tu pago, necesitamos que subas tu boleta de honorarios en formato PDF a través de la plataforma.
Datos para generar la boleta en el SII:
Razón Social: Pontificia Universidad Católica de Chile
RUT: 81.698.900-0
Dirección: Avda. Libertador Bernardo O\'Higgins N 340, Santiago
Monto: $' . number_format($monto, 0, ',', '.') . '
Saludos cordiales,
Equipo de Difusión UC';
$mensajes->enviar5Mensaje(
$nominapago->getEmbajador()->getCorreo(),
'vivian.avalos@uc.cl',
$asunto,
$cuerpo
);
}
}
/**
* @Route("/borrar2/{id}", name="app_embajador_participante_delete_byuser", methods={"GET", "POST"})
*/
public function deletebyuser(Request $request, EmbajadorParticipante $embajadorParticipante, EmbajadorParticipanteRepository $embajadorParticipanteRepository): Response
{
$user = $this->getUser();
if ($this->isGranted('ROLE_ESTUDIANTE') and $user->getId() == $embajadorParticipante->getEmbajadores()->getId()) {
$id = $embajadorParticipante->getAgenda()->getId();
//if ($this->isCsrfTokenValid('delete'.$embajadorParticipante->getId(), $request->request->get('_token'))) {
$embajadorParticipanteRepository->remove($embajadorParticipante, true);
//}
return $this->redirectToRoute('agenda_index_estudiante');
}
}
/**
* @Route("/correo/{id}", name="app_embajador_participante_correo", methods={"GET", "POST"})
*/
public function newferiasolicitud( Mensajes $mensajes, $id, Request $request, EmbajadorParticipante $embajadorParticipante): Response
{
$entityManager = $this->getDoctrine()->getManager();
if($embajadorParticipante->getCorreo()){
$msj = $embajadorParticipante->getCorreo();
} else {
$msj=
"Hola,<br><br>
Has sido seleccionado para la actividad <strong>".$embajadorParticipante->getAgenda()->getTipoAgenda()->getNombre()."</strong>, el día <strong>".date_format($embajadorParticipante->getAgenda()->getFecha(),"d/m/Y")."</strong>, en <strong>".$embajadorParticipante->getAgenda()->getLugar()."</strong> con el rol: <strong>".$embajadorParticipante->getRol()."</strong><br><br>
".$embajadorParticipante->getAgenda()->getTipoAgenda()->getCuerpo()."<br><br>
Para más detalles de la actividad puedes revisar la plataforma Delfy.<br><br>
Saludos cordiales";
}
$mensajes->enviar2Mensaje($embajadorParticipante->getEmbajadores()->getCorreo(),"vivian.avalos@uc.cl", "Actividad asignada", $msj);
$embajadorParticipante->setEnviado(True);
$entityManager->persist($embajadorParticipante);
$entityManager->flush();
return $this->redirectToRoute('app_embajador_participante_newbyagenda', array('id' => $embajadorParticipante->getAgenda()->getId()));
}
}