<?php
namespace App\Controller\higotrigo;
use App\Entity\HtExtra;
use App\Entity\HtFile;
use App\Entity\HtFileDeposit;
use App\Entity\HtInvoice;
use App\Entity\HtProforma;
use App\Form\HtFileDepositType;
use App\Form\HtFileType;
use App\MDS\VenuesBundle\Entity\Reservation;
use App\MDS\VenuesBundle\Entity\ReservationLoungeSimple;
use App\Repository\HtFileRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use App\Entity\User;
use App\Helper\StatusHelper;
use App\MDS\AvexpressBundle\Entity\AveFiles;
use App\Service\HtService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/higotrigo/ht/file")
*/
class HtFileController extends AbstractController
{
private HtFileRepository $htFileRepository;
private EntityManagerInterface $em;
private LoggerInterface $htLogger;
private SessionInterface $session;
public function __construct(HtFileRepository $htFileRepository, LoggerInterface $htLogger, SessionInterface $session, EntityManagerInterface $em) {
$this->htFileRepository = $htFileRepository;
$this->htLogger = $htLogger;
$this->session = $session;
$this->em = $em;
}
/**
* @Route("/", name="app_ht_file_index", methods={"GET"})
*/
public function index(): Response
{
$htFile = $this->htFileRepository->findAll();
return $this->render('higotrigo/ht_file/index.html.twig', [
'ht_files' => $htFile,
]);
}
/**
* @Route("/new", name="app_ht_file_new", methods={"GET", "POST"})
*/
public function new(Request $request): Response
{
$htFile = new HtFile();
$form = $this->createForm(HtFileType::class, $htFile);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $this->getUser();
$htFile->setCreatedId($user);
$htFile->setUpdatedId($user);
$htFile = $this->_addUserToExtras($htFile, $user);
$this->htFileRepository->add($htFile, true);
return $this->redirectToRoute('app_ht_file_edit', ['id' => $htFile->getId()], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('higotrigo/ht_file/new.html.twig', [
'ht_file' => $htFile,
'invoices' => null,
'form' => $form,
]);
}
/**
* @Route("/{id}", name="app_ht_file_show", methods={"GET"})
*/
public function show(HtFile $htFile): Response
{
return $this->render('higotrigo/ht_file/show.html.twig', [
'ht_file' => $htFile,
]);
}
/**
* @Route("/{id}/edit", name="app_ht_file_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, HtFile $htFile, HtService $htService): Response
{
// 1. Extraemos la reserva vinculada de Venues
$reservation = $htFile->getReservation();
// dd($reservation->getId());
// 2. Pasamos la reserva como opción al formulario
$form = $this->createForm(HtFileType::class, $htFile, [
'reservation' => $reservation
]);
$form->handleRequest($request);
// ... (resto del código del depósito)
$deposit = new HtFileDeposit();
$deposit->setFileId($htFile->getId());
$depositForm = $this->createForm(HtFileDepositType::class, $deposit, [
'user' => $this->getUser(),
'action' => $this->generateUrl('ht_deposit_save', ['fileId' => $htFile->getId()]),
'method' => 'POST',
]);
$invoices = $this->em->getRepository(HtInvoice::class)->findByHtFile($htFile);
$proformas = $this->em->getRepository(HtProforma::class)->findByHtFile($htFile->getId());
$deposits = $this->em->getRepository(HtFileDeposit::class)->findByFileId($htFile->getId());
$gpFile = !empty($reservation) && $this->session->get('_modules')->mvenues ? $reservation : null;
$aveFile = !empty($gpFile) && $this->session->get('_modules')->mav ? $this->em->getRepository(AveFiles::class)->findOneByReservation($gpFile) : null;
return $this->renderForm('higotrigo/ht_file/edit.html.twig', [
'ht_file' => $htFile,
'invoices' => $invoices,
'proformas' => $proformas,
'deposits' => $deposits,
'gpFile' => $gpFile,
'aveFile' => $aveFile,
'form' => $form,
'depositForm' => $depositForm,
'isNew' => true,
'totalData' => $htService->CalcTotals($htFile),
]);
}
/**
* @Route("/{id}/edit/ajax", name="app_ht_file_edit_ajax", methods={"POST"})
*/
public function editAjax(Request $request, HtFile $htFile): JsonResponse
{
$originalStatus = $htFile->getStatus();
$originalClient = $htFile->getClient();
$form = $this->createForm(HtFileType::class, $htFile);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$this->_processFileUpdate($htFile, $originalStatus, $originalClient);
return $this->json([
'msg' => 'Datos guardados correctamente',
'data' => []
], JsonResponse::HTTP_OK);
} catch (\Throwable $th) {
return $this->json([
'title' => 'Ha ocurrido un error al guardar los datos',
'msg' => $th->getMessage(),
'data' => []
], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
$this->htLogger->error(sprintf(
'Expediente %d: %s',
$htFile->getId(),
$th->getMessage()
));
}
}
return $this->json([
'title' => 'Error al enviar los datos',
'msg' => 'Revisa el formulario',
'data' => $this->_getFormErrorsAsArray($form)
], JsonResponse::HTTP_BAD_REQUEST);
}
/**
* @Route("/{id}", name="app_ht_file_delete", methods={"POST"})
*/
public function delete(Request $request, HtFile $htFile): Response
{
if ($this->isCsrfTokenValid('delete'.$htFile->getId(), $request->request->get('_token'))) {
$this->htFileRepository->remove($htFile, true);
}
return $this->redirectToRoute('app_ht_file_index', [], Response::HTTP_SEE_OTHER);
}
/**
* @Route("/htexternal/{id}/summary", name="app_ht_file_summary", methods={"GET", "POST"})
*/
public function summary(HtFile $htFile): Response
{
$arrayElem = array();
$htItems = $htFile->getHtItems();
if(!empty($htItems)) {
foreach ($htItems as $htItem) {
$arrayEscandallos = [];
$arrayMenus = [];
$lounge = empty($htItem->getLoungeGp()) ? $htItem->getLoungeOther() : $htItem->getLoungeGp()->getName();
$lounge = empty($lounge) ? 'No se ha indicado la sala' : $lounge;
if (!empty($htItem->getHtMenus())) {
foreach (($htItem->getHtMenus()) as $htMenu){
foreach (($htMenu->getEscandallo()) as $escan){
$arrayEscandallos[] = array('escandallo' => $escan, 'nota' => $escan->getHtNotes()[0],);
}
$arrayMenus[] = array('htMenu' => $htMenu, 'arrayEscandallos' => $arrayEscandallos,);
}
}
$arrayElem[$htItem->getDateStart()->format('YmdHi').str_pad($htItem->getId(), 6, "0", STR_PAD_LEFT)] = array(
'htItem'=>$htItem,
'htMenus'=> $arrayMenus,
'lounge'=>$lounge,
);
}
}
ksort($arrayElem);
$reserva = null; $lngMont = null; $lngDesMont = null;
$reservaIdNotLinked = $htFile->getReservation();
if (!empty($reservaIdNotLinked)){ $reserva = $this->em->getRepository(Reservation::class)->findOneById($reservaIdNotLinked->getId()); }
if (!empty($reserva)){
$lngMont = $this->em->getRepository(ReservationLoungeSimple::class)->findOneBy( array( 'idReservation' => $reserva->getId(), 'type' => 'Montaje', ) );
$lngDesMont = $this->em->getRepository(ReservationLoungeSimple::class)->findOneBy( array( 'idReservation' => $reserva->getId(), 'type' => 'Desmontaje', ) );
}
return $this->renderForm('higotrigo/ht_file/summary-htfile-pdf.html.twig', [
'ht_file' => $htFile,
'arrayElem' => $arrayElem,
'reserva' => $reserva,
'montaje' => $lngMont,
'desmontaje' => $lngDesMont,
]);
}
/**
* Recorremos los extras para añadirle el usuario que los crea y edita
*/
private function _addUserToExtras(HtFile $htFile, User $user) : HtFile {
$htItems = $htFile->getHtItems();
foreach ($htItems as $htItem) {
$htFile->removeHtItem($htItem); // Borrar el item para volverlo a insertar al final con los cambios de extras
$htExtras = $htItem->getHtExtras();
foreach ($htExtras as $htExtra) {
$htItem->removeHtExtra($htExtra);
if($htExtra->getCreatedId() == NULL){
$htExtra->setCreatedId($user);
}
$htExtra->setUpdatedId($user);
$htItem->addHtExtra($htExtra);
}
$htFile->addHtItem($htItem);
}
return $htFile;
}
/**
* Comprobar si el htFile tiene htItems y si estos tienen htExtras para añadirselos para que la vista funcione bien.
*/
private function _addHtItemAndHtExtra(HtFile $htFile) : HtFile {
$htItems = $htFile->getHtItems();
if($htItems){
foreach ($htItems as $htItem) {
$htExtras = $htItem->getHtExtras();
if($htExtras === null || $htExtras->isEmpty()){
$htFile->removeHtItem($htItem);
$htExtra = new HtExtra();
$htItem->addHtExtra($htExtra);
$htFile->addHtItem($htItem);
}
}
}
return $htFile;
}
/**
* Procesa la actualización de la entidad HtFile (Auditoría, Asignación de usuario y Persistencia).
*/
private function _processFileUpdate(HtFile $htFile, string $originalStatus, ?object $originalClient): void
{
// Si el estado es facturado pero no tiene factura, no se permite guardar
$invoices = $this->em->getRepository(HtInvoice::class)->findByHtFile($htFile);
if ($htFile->getStatus() === StatusHelper::STATUS_HT['Facturado'] && !$invoices) {
throw new \Exception('No se puede establecer el estado "Facturado" sin tener al menos una factura asociada');
}
// Controlar que las fechas de inicio es menor que la de fin
// if ($htFile->getDateStart() && $htFile->getDateEnd() && $htFile->getDateStart() > $htFile->getDateEnd()) {
// throw new \Exception('La fecha de inicio no puede ser mayor que la fecha de fin');
// }
if ($originalStatus !== $htFile->getStatus()) {
$this->htLogger->info(sprintf(
'Expediente %d: status cambiado de "%s" a "%s"',
$htFile->getId(),
$originalStatus,
$htFile->getStatus()
));
}
if ($originalClient !== $htFile->getClient()) {
$this->htLogger->info(sprintf(
'Expediente %d: cliente cambiado de "%s" a "%s". El usuario que realiza el cambio es %s',
$htFile->getId(),
$originalClient ? $originalClient->getName() : 'N/A',
$htFile->getClient() ? $htFile->getClient()->getName() : 'N/A',
$this->getUser() ? $this->getUser()->getEmail() : 'unknown'
));
}
$user = $this->getUser();
$htFile->setUpdatedId($user);
$htFile = $this->_addUserToExtras($htFile, $user);
$this->htFileRepository->add($htFile, true);
}
private function _getFormErrorsAsArray(\Symfony\Component\Form\FormInterface $form): array
{
$errors = [];
// Errores globales del formulario (como el Callback que pusimos en la entidad)
foreach ($form->getErrors() as $error) {
$errors[] = $error->getMessage();
}
// Errores específicos de cada campo
foreach ($form->all() as $child) {
if (!$child->isValid()) {
foreach ($child->getErrors(true) as $error) {
// Guardamos el error con el nombre del campo para identificarlo en el JS
$errors[$child->getName()] = $error->getMessage();
}
}
}
return $errors;
}
}