src/Controller/CallcenterController.php line 64

  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Cabecera;
  4. use App\Entity\ClienteBitcubo;
  5. use App\Entity\ClienteEnvioBitcubo;
  6. use App\Entity\Configuracion;
  7. use App\Entity\CabeceraStatus;
  8. use App\Entity\CabeceraLinkdepago;
  9. use App\Entity\Domicilios;
  10. use App\Entity\Lineas;
  11. use App\Entity\Sucursal;
  12. use App\Form\Type\CabeceraType;
  13. use App\Form\Type\Cabecera2Type;
  14. use App\Form\Type\CabeceraEmailLinkdepagoType;
  15. use App\Form\Type\LineasType;
  16. use App\Repository\ArticulosRepository;
  17. use App\Repository\ClientesRepository;
  18. use App\Repository\ClienteBitcuboRepository;
  19. use App\Repository\FavoritoscabRepository;
  20. use App\Repository\LineasRepository;
  21. use App\Repository\ModificadoreslinRepository;
  22. use App\Repository\SucursalRepository;
  23. use App\Service\EstadisticasArticulosService;
  24. use App\Utils\Status;
  25. use App\Utils\Xml;
  26. use Doctrine\ORM\EntityManagerInterface;
  27. use Doctrine\Persistence\ManagerRegistry;
  28. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  29. use Symfony\Component\Filesystem\Filesystem;
  30. use Symfony\Component\Form\Extension\Core\Type\TextType;
  31. use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
  32. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  33. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  34. use Symfony\Component\HttpFoundation\Request;
  35. use Symfony\Component\HttpFoundation\Response;
  36. // use Symfony\Component\HttpFoundation\Session\Session;
  37. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  38. use Symfony\Component\Routing\Annotation\Route;
  39. use App\Controller\Admin\CabeceraCrudController;
  40. use App\Repository\ImpuestosRepository;
  41. use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  42. use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
  43. use App\Service\ClienteManager;
  44. use App\Service\GlobalPayService;
  45. use App\Service\MailerService;
  46. use App\Service\XmlGeneratorService;
  47. use App\Service\ConectorPlusCatalogService;
  48. use Psr\Log\LoggerInterface;
  49. // use ParagonIE\Halite\KeyFactory;
  50. class CallcenterController extends AbstractController
  51. {
  52.     use Status;
  53.     private $adminUrlGenerator;
  54.     public function __construct(
  55.         private ManagerRegistry $doctrine,
  56.         AdminUrlGenerator $adminUrlGenerator,
  57.         private ConectorPlusCatalogService $catalogService,
  58.         private LoggerInterface $logger,
  59.     ) {
  60.         $this->doctrine $doctrine;
  61.         $this->adminUrlGenerator $adminUrlGenerator;
  62.     }
  63.     #[Route('/'name'callcenter')]
  64.     public function index(Request $request): Response
  65.     
  66.         // $keyPath = $this->getParameter('kernel.project_dir') . '/config/encryption.key';
  67.         // if (file_exists($keyPath)) {
  68.         //     return new Response('La clave de cifrado ya existe. No se generó una nueva clave.', 403);
  69.         // }
  70.         // $encryptionKey = KeyFactory::generateEncryptionKey();
  71.         // KeyFactory::save($encryptionKey, $keyPath);
  72.         // $keyPath = $this->getParameter('encryption_key_path');
  73.         // dd($keyPath);
  74.         $dataFromRequest  $request->get('data');
  75.         $formData = [];
  76.         if ($dataFromRequest) {
  77.             $formData = [
  78.                 'type' => $dataFromRequest['type'], // Usar valores por defecto si las claves no existen
  79.                 'text' => $dataFromRequest['text'] ?? '',
  80.                 'factura_electronica' => $dataFromRequest['fe'] ? true false,
  81.             ];
  82.         }
  83.         if (!array_key_exists('type'$formData)) {
  84.             $formData['type'] = 1;
  85.         }
  86.         $form $this->createFormBuilder($formData)
  87.             ->add('type'ChoiceType::class, [
  88.                 'choices' => [
  89.                     'Telefono' => 1,
  90.                     'Documento' => 2
  91.                 ],
  92.                 'expanded' => true,
  93.                 'multiple' => false,
  94.             ])
  95.             ->add('text'TextType::class)
  96.             ->add('factura_electronica'CheckboxType::class, [
  97.                 'required' => false,
  98.             ])
  99.             ->add('buscar'SubmitType::class)
  100.             ->getForm();
  101.         $form->handleRequest($request);
  102.         if ($form->isSubmitted() && $form->isValid()) {
  103.             $data $form->getData();
  104.             return $this->redirectToRoute(
  105.                 'seleccionCliente',
  106.                 array(
  107.                     'type' => $data['type'],
  108.                     'text' => $data['text'],
  109.                     'fe' => $data['factura_electronica'] ? '1' '0',
  110.                 )
  111.             );
  112.         }
  113.         return $this->render('callcenter/index.html.twig', [
  114.             'form' => $form->createView(),
  115.         ]);
  116.     }
  117.     #[Route('/selecciondecliente/{type}/{text}/{fe}'name'seleccionCliente')]
  118.     public function seleccionCliente(
  119.         int $type,
  120.         string $text,
  121.         string $fe,
  122.         ClientesRepository $clienteRepository,
  123.         ClienteBitcuboRepository $clienteBitcuboRepository,
  124.         SessionInterface $session
  125.     ): Response {
  126.         $data = [
  127.             'type' => $type,
  128.             'text' => $text,
  129.             'fe' => filter_var($feFILTER_VALIDATE_BOOLEAN)
  130.         ];
  131.         $cliente $this->buscarCliente($data$clienteRepository$clienteBitcuboRepository);
  132.         if (empty($cliente)) {
  133.             return $this->manejarClienteNoEncontrado($data$session);
  134.         }
  135.         if (count($cliente) === 1) {
  136.             return $this->manejarClienteUnico($cliente[0], $data['fe'], $session);
  137.         }
  138.         return $this->manejarMultiplesClientes($cliente$data$session);
  139.     }
  140.     private function buscarCliente(array $dataClientesRepository $clienteRepositoryClienteBitcuboRepository $clienteBitcuboRepository): array
  141.     {
  142.         $cliente $clienteRepository->findClient($data);
  143.         if (!$data['fe'] && empty($cliente)) {
  144.             // Buscar en ClienteBitcuboRepository si no hay resultados en ClientesRepository
  145.             if ($data['type'] === 1) {
  146.                 $clienteBitcubo $clienteBitcuboRepository->findBy(['telefonocliente' => $data['text']]);
  147.             } else {
  148.                 $clienteBitcubo $clienteBitcuboRepository->findBy(['nifcliente' => $data['text']]);
  149.             }
  150.             if (!empty($clienteBitcubo)) {
  151.                 $cliente array_map(function($bitcubo) {
  152.                     $ultima_direccion $bitcubo->getDirecciones()->isEmpty() ? null $bitcubo->getDirecciones()->last();
  153.                     return [
  154.                         'codcliente' => $bitcubo->getId(),
  155.                         'nombrecliente' => $bitcubo->getNombres() . ' ' $bitcubo->getApellidos(),
  156.                         // 'apellidos' => $bitcubo->getApellidos(),
  157.                         'telefono1' => $bitcubo->getTelefonocliente(),
  158.                         'emailcliente' => $bitcubo->getEmailcliente(),
  159.                         'nif20' => $bitcubo->getNifcliente(),
  160.                         'alias' => null,
  161.                         'direccion1' => $ultima_direccion $ultima_direccion->getDireccion() : '',
  162.                         'direccion_2' => $ultima_direccion $ultima_direccion->getComplemento() : '',
  163.                         'cl_nombre_1' => $bitcubo->getNombres(),
  164.                         'otros_nombres' => null,
  165.                         'cl_apellido_1' => $bitcubo->getApellidos(),
  166.                         'cl_apellido_2' => null,
  167.                         'tipo_de_documento' => null,
  168.                         'tipopersona' => null,
  169.                         'fe_det_tributario' => null,
  170.                         'fe_responsabilidades' => null,
  171.                         'direcciones_bitcubo' => $bitcubo->getDirecciones(),
  172.                         'es_cliente_bitcubo' => true,
  173.                     ];
  174.                 }, $clienteBitcubo);
  175.             }
  176.         }
  177.         return $cliente;
  178.     }
  179.     private function manejarClienteNoEncontrado(array $dataSessionInterface $session): Response
  180.     {
  181.         if ($data['fe']) {
  182.             $qrRoute 'https://qrmde.crepesywaffles.com/qrcc/qrmde.php';
  183.             $this->addFlash(
  184.                 'notice',
  185.                 'DEBES CREAR EL CLIENTE PRIMERO EN EL QR PARA FACTURA ELECTRÓNICA <a class="alert-link" href="' $qrRoute '" target="_blank">Crear QR</a>'
  186.             );
  187.             return $this->redirectToRoute('callcenter', ['data' => $data]);
  188.         }
  189.         $session->set('clienteData'$data);
  190.         $session->set('fe'$data['fe']);
  191.         // Temporal: redirect a cliente_v2 para probar la nueva versión
  192.         return $this->redirectToRoute('cliente_v2');
  193.     }
  194.     private function manejarClienteUnico(array $clientebool $feSessionInterface $session): Response
  195.     {
  196.         $session->set('clienteData'$cliente);
  197.         $session->set('fe'$fe);
  198.         // Temporal: redirect a cliente_v2 para probar la nueva versión
  199.         return $this->redirectToRoute('cliente_v2');
  200.     }
  201.     private function manejarMultiplesClientes(array $clientes, array $dataSessionInterface $session): Response
  202.     {
  203.         $session->set('clienteData'$clientes);
  204.         return $this->render('callcenter/clienteSelect.html.twig', [
  205.             'clientes' => $clientes,
  206.             'data' => $data
  207.         ]);
  208.     }
  209.         // $feBool = filter_var($fe, FILTER_VALIDATE_BOOLEAN);
  210.         // $data = ['type' => $type, 'text' => $text, 'fe' => $feBool];
  211.         // $cliente = $clienteRepository->findClient($data);
  212.         // if (empty($cliente)) {
  213.         //     if ($feBool) {
  214.         //         $qrRoute = 'https://qrmde.crepesywaffles.com/qrcc/qrmde.php';
  215.         //         $this->addFlash(
  216.         //             'notice',
  217.         //             'DEBES CREAR EL CLIENTE PRIMERO EN EL QR PARA FACTURA ELECTRÓNICA <a class="alert-link" href="' . $qrRoute . '" target="_blank">Crear QR</a>'
  218.         //         );
  219.         //         return $this->redirectToRoute('callcenter', ['data' => $data]);
  220.         //     } else {
  221.         //         $session->set('clienteData', $data); // Guardar en sesión
  222.         //         $session->set('fe', $data['fe']); // Guardar en sesión
  223.         //         return $this->redirectToRoute('cliente');
  224.         //     }
  225.         // } elseif (count($cliente) === 1) {
  226.         //     $session->set('clienteData', $cliente[0]); // Guardar en sesión
  227.         //     $session->set('fe', $data['fe']); // Guardar en sesión
  228.         //     return $this->redirectToRoute('cliente');
  229.         // }
  230.         // $session->set('clienteData', $cliente);
  231.         // return $this->render('callcenter/clienteSelect.html.twig', ['clientes' => $cliente, 'data' => $data]);
  232.     // }
  233.     #[Route('/cliente-v2'name'cliente_v2')]
  234.     public function clienteV2(Request $requestSessionInterface $sessionClienteManager $clienteManagerSucursalRepository $sucursalRepository): Response
  235.     {
  236.         $clienteData $session->get('clienteData');
  237.         $fe $session->get('fe');
  238.         $clienteData $clienteData[$request->get('index')]  ?? $clienteData;
  239.         $cabecera $clienteManager->procesarDatosCliente($clienteData);
  240.         $cabecera->setFacturaelectronica($fe 0);
  241.         if (isset($clienteData['es_cliente_bitcubo'])) {
  242.             $editable false;
  243.         } else {
  244.             $editable = isset($clienteData['alias']) ? !($clienteData['alias'] === "1") : true;
  245.         }
  246.         $form $this->createForm(CabeceraType::class, $cabecera, ['editable_mode' => $editable]);
  247.         $form->handleRequest($request);
  248.         // Obtener sucursales disponibles (solo las que tienen catálogo configurado)
  249.         $sucursales $sucursalRepository->findAvailable();
  250.         if ($form->isSubmitted() && $form->isValid()) {
  251.             // Lógica de guardado
  252.             $entityManager $this->doctrine->getManager();
  253.             if (!isset($clienteData['es_cliente_bitcubo']) and !isset($clienteData['codcliente'])) {
  254.                 // Verificar si ya existe un cliente con el mismo nifcliente para evitar duplicados
  255.                 $cliente_bitcubo $entityManager->getRepository(ClienteBitcubo::class)->findOneBy([
  256.                     'nifcliente' => $cabecera->getNifcliente()
  257.                 ]);
  258.                 if (!$cliente_bitcubo) {
  259.                     // Solo crear si no existe
  260.                     $cliente_bitcubo = new ClienteBitcubo();
  261.                     $cliente_bitcubo->setNombres($cabecera->getNombres());
  262.                     $cliente_bitcubo->setApellidos($cabecera->getApellidos());
  263.                     $cliente_bitcubo->setTelefonocliente($cabecera->getTelefonocliente());
  264.                     $cliente_bitcubo->setEmailcliente($cabecera->getEmailcliente());
  265.                     $cliente_bitcubo->setNifcliente($cabecera->getNifcliente());
  266.                     $entityManager->persist($cliente_bitcubo);
  267.                     $entityManager->flush();
  268.                 }
  269.                 $clienteData['codcliente'] = $cliente_bitcubo->getId();
  270.                 // Agregar dirección si no existe
  271.                 $direccionExistente $entityManager->getRepository(ClienteEnvioBitcubo::class)->findOneBy([
  272.                     'cliente_bitcubo' => $cliente_bitcubo,
  273.                     'direccion' => $cabecera->getDireccionCliente(),
  274.                     'complemento' => $cabecera->getDireccion2Cliente(),
  275.                 ]);
  276.                 if (!$direccionExistente) {
  277.                     $cliente_envio_bitcubo = new ClienteEnvioBitcubo();
  278.                     $cliente_envio_bitcubo->setDireccion($cabecera->getDireccionCliente());
  279.                     $cliente_envio_bitcubo->setComplemento($cabecera->getDireccion2Cliente());
  280.                     $cliente_envio_bitcubo->setLatitud($cabecera->getLatitud());
  281.                     $cliente_envio_bitcubo->setLongitud($cabecera->getLongitud());
  282.                     $cliente_bitcubo->addDireccion($cliente_envio_bitcubo);
  283.                     $entityManager->persist($cliente_envio_bitcubo);
  284.                     $entityManager->flush();
  285.                 }
  286.             } else {
  287.                 $cliente_bitcubo $entityManager->getRepository(ClienteBitcubo::class)->find($clienteData['codcliente']);
  288.                 if ($cliente_bitcubo) {
  289.                     $direccionExistente $entityManager->getRepository(ClienteEnvioBitcubo::class)->findOneBy([
  290.                         'cliente_bitcubo' => $cliente_bitcubo,
  291.                         'direccion' => $cabecera->getDireccionCliente(),
  292.                         'complemento' => $cabecera->getDireccion2Cliente(),
  293.                     ]);
  294.                     if (!$direccionExistente) {
  295.                         $cliente_envio_bitcubo = new ClienteEnvioBitcubo();
  296.                         $cliente_envio_bitcubo->setDireccion($cabecera->getDireccionCliente());
  297.                         $cliente_envio_bitcubo->setComplemento($cabecera->getDireccion2Cliente());
  298.                         $cliente_envio_bitcubo->setLatitud($cabecera->getLatitud());
  299.                         $cliente_envio_bitcubo->setLongitud($cabecera->getLongitud());
  300.                         $cliente_bitcubo->addDireccion($cliente_envio_bitcubo);
  301.                         $entityManager->persist($cliente_envio_bitcubo);
  302.                         $entityManager->flush();
  303.                     }
  304.                 }
  305.             }
  306.             if ($cabecera->getNombreReceptor() === null || $cabecera->getNombreReceptor() === '') {
  307.                 $cabecera->setNombreReceptor($cabecera->getNombrecliente());
  308.             }
  309.             if ($cabecera->getTelefonoReceptor() === null || $cabecera->getTelefonoReceptor() === '') {
  310.                 $cabecera->setTelefonoReceptor($cabecera->getTelefonocliente());
  311.             }
  312.             $clienteManager->guardarCabecera($cabecera$this->getuser());
  313.             return $this->redirectToRoute('cc_favoritos', ['id' => $cabecera->getId()]);
  314.         }
  315.         // Parámetros de tiempo mínimo para reservas (desde config/services/bitcubo.yaml)
  316.         // Se pasan a JavaScript para validación en frontend
  317.         $horareserva $this->getParameter('app.bc.horareserva'); // +60 minutos para DOMICILIO/PROGRAMAR
  318.         $horaclienterecoge $this->getParameter('app.bc.horaclienterecoge'); // +30 minutos para RECOGER
  319.         return $this->render('callcenter/cliente_v2.html.twig', [
  320.             'cliente' => $clienteData,
  321.             'form' => $form->createView(),
  322.             'sucursales' => $sucursales,
  323.             'horareserva' => $horareserva,
  324.             'horaclienterecoge' => $horaclienterecoge,
  325.         ]);
  326.     }
  327.     #[Route('/cliente'name'cliente')]
  328.     public function cliente(Request $requestSessionInterface $sessionClienteManager $clienteManagerSucursalRepository $sucursalRepository): Response
  329.     {
  330.         $clienteData $session->get('clienteData');
  331.         $fe $session->get('fe');
  332.         $clienteData $clienteData[$request->get('index')]  ?? $clienteData;
  333.         $cabecera $clienteManager->procesarDatosCliente($clienteData);
  334.         $cabecera->setFacturaelectronica($fe 0);
  335.         if (isset($clienteData['es_cliente_bitcubo'])) {
  336.             $editable false;
  337.         } else {
  338.             $editable = isset($clienteData['alias']) ? !($clienteData['alias'] === "1") : true;
  339.         }
  340.         $form $this->createForm(CabeceraType::class, $cabecera, ['editable_mode' => $editable]);
  341.         $form->handleRequest($request);
  342.         if ($form->isSubmitted() && $form->isValid()) {
  343.             // Guarda si el cliente es nuevo en cliente_bitcubo
  344.             $entityManager $this->doctrine->getManager();
  345.             if (!isset($clienteData['es_cliente_bitcubo']) and !isset($clienteData['codcliente'])) {
  346.                 // Verificar si ya existe un cliente con el mismo nifcliente para evitar duplicados
  347.                 $cliente_bitcubo $entityManager->getRepository(ClienteBitcubo::class)->findOneBy([
  348.                     'nifcliente' => $cabecera->getNifcliente()
  349.                 ]);
  350.                 if (!$cliente_bitcubo) {
  351.                     // Solo crear si no existe
  352.                     $cliente_bitcubo = new ClienteBitcubo();
  353.                     $cliente_bitcubo->setNombres($cabecera->getNombres());
  354.                     $cliente_bitcubo->setApellidos($cabecera->getApellidos());
  355.                     $cliente_bitcubo->setTelefonocliente($cabecera->getTelefonocliente());
  356.                     $cliente_bitcubo->setEmailcliente($cabecera->getEmailcliente());
  357.                     $cliente_bitcubo->setNifcliente($cabecera->getNifcliente());
  358.                     $entityManager->persist($cliente_bitcubo);
  359.                     $entityManager->flush();
  360.                 }
  361.                 $clienteData['codcliente'] = $cliente_bitcubo->getId();
  362.                 // Agregar dirección si no existe
  363.                 $direccionExistente $entityManager->getRepository(ClienteEnvioBitcubo::class)->findOneBy([
  364.                     'cliente_bitcubo' => $cliente_bitcubo,
  365.                     'direccion' => $cabecera->getDireccionCliente(),
  366.                     'complemento' => $cabecera->getDireccion2Cliente(),
  367.                 ]);
  368.                 if (!$direccionExistente) {
  369.                     $cliente_envio_bitcubo = new ClienteEnvioBitcubo();
  370.                     $cliente_envio_bitcubo->setDireccion($cabecera->getDireccionCliente());
  371.                     $cliente_envio_bitcubo->setComplemento($cabecera->getDireccion2Cliente());
  372.                     $cliente_envio_bitcubo->setLatitud($cabecera->getLatitud());
  373.                     $cliente_envio_bitcubo->setLongitud($cabecera->getLongitud());
  374.                     $cliente_bitcubo->addDireccion($cliente_envio_bitcubo);
  375.                     $entityManager->persist($cliente_envio_bitcubo);
  376.                     $entityManager->flush();
  377.                 }
  378.             } else {
  379.                 $cliente_bitcubo $entityManager->getRepository(ClienteBitcubo::class)->find($clienteData['codcliente']);
  380.                 if ($cliente_bitcubo) {
  381.                     // Verificar si la dirección ya existe para este cliente
  382.                     $direccionExistente $entityManager->getRepository(ClienteEnvioBitcubo::class)->findOneBy([
  383.                         'cliente_bitcubo' => $cliente_bitcubo,
  384.                         'direccion' => $cabecera->getDireccionCliente(),
  385.                         'complemento' => $cabecera->getDireccion2Cliente(),
  386.                     ]);
  387.                     if (!$direccionExistente) {
  388.                         // La dirección no existe, se agrega
  389.                         $cliente_envio_bitcubo = new ClienteEnvioBitcubo();
  390.                         $cliente_envio_bitcubo->setDireccion($cabecera->getDireccionCliente());
  391.                         $cliente_envio_bitcubo->setComplemento($cabecera->getDireccion2Cliente());
  392.                         $cliente_envio_bitcubo->setLatitud($cabecera->getLatitud());
  393.                         $cliente_envio_bitcubo->setLongitud($cabecera->getLongitud());
  394.                         $cliente_bitcubo->addDireccion($cliente_envio_bitcubo);
  395.                         $entityManager->persist($cliente_envio_bitcubo);
  396.                         $entityManager->flush();
  397.                     }
  398.                 }
  399.             }
  400.             if ($cabecera->getNombreReceptor() === null || $cabecera->getNombreReceptor() === '') {
  401.                 $cabecera->setNombreReceptor($cabecera->getNombrecliente());
  402.             }
  403.             if ($cabecera->getTelefonoReceptor() === null || $cabecera->getTelefonoReceptor() === '') {
  404.                 $cabecera->setTelefonoReceptor($cabecera->getTelefonocliente());
  405.             }
  406.             $clienteManager->guardarCabecera($cabecera$this->getuser());
  407.             return $this->redirectToRoute('cc_favoritos', ['id' => $cabecera->getId()]);
  408.         }
  409.         $sucursales $sucursalRepository->findAvailable();
  410.         return $this->render('callcenter/cliente.html.twig', [
  411.             'cliente' => $clienteData,
  412.             'form' => $form->createView(),
  413.             'sucursales' => $sucursales,
  414.         ]);
  415.     }
  416. // Todo cliente nuevo o sin alias 1 debe crearse en bitcubo
  417. // ?? que pasa con la dirección nueva de un cliente con factura electrónica, si pide el mismo día.??
  418. // --------------------
  419. // Top 10: cambiar la forma en la que se graba el codcliente y tener en cuenta los de bitcubo. para poder buscar todas las cabeceras de dicho cliente
  420. //
  421.     #[Route('/cabecera/{id}/editar'name'cliente_editar')]
  422.     public function clienteEdit(SucursalRepository $sucursalRepositoryRequest $requestint $id\App\Service\ConnectorStoreResolver $connectorStoreResolver): Response
  423.     {
  424.         $cabecera $this->doctrine->getRepository(Cabecera::class)->find($id);
  425.         $editable $cabecera->getAlias() === "1" false true;
  426.         if ($cabecera->getAlias() === "1") {
  427.             $editable false;
  428.         } else if($cabecera->getCodcliente()) {
  429.             $editable false;
  430.         } else {
  431.             $editable true;
  432.         }
  433.         if (!$cabecera) {
  434.             throw $this->createNotFoundException(
  435.                 'Cabecera no encontrada'
  436.             );
  437.         }
  438.         $estados = array('INICIADO''EDICION');
  439.         if (!in_array($cabecera->getEstado(), $estados)) {
  440.             throw $this->createNotFoundException(
  441.                 'NO SE PUEDE EDITAR ESTE PEDIDO'
  442.             );
  443.         }
  444.         $sucursales $sucursalRepository->findAvailable();
  445.         $form $this->createForm(CabeceraType::class, $cabecera, ['editable_mode' => $editable]);
  446.         $form->handleRequest($request);
  447.         if ($form->isSubmitted() && $form->isValid()) {
  448.             $cabecera $form->getData();
  449.             // Actualizar ConnectorStore si cambió la sucursal
  450.             $connectorStoreResolver->resolveConnectorStore($cabecera);
  451.             $entityManager $this->doctrine->getManager();
  452.             $entityManager->persist($cabecera);
  453.             $entityManager->flush();
  454.             return $this->redirectToRoute('cc_favoritos', [
  455.                 'id' => $cabecera->getId()
  456.             ]);
  457.         }
  458.         return $this->render('callcenter/cliente_v2.html.twig', [
  459.             'cliente' => $cabecera,
  460.             'form' => $form->createView(),
  461.             'sucursales' => $sucursales,
  462.         ]);
  463.     }
  464.     #[Route('/cabecera/{id}/favoritos'name'cc_favoritos')]
  465.     public function favoritos(int $id): Response {
  466.         // Redireccionar al nuevo método del OrderController
  467.         // que maneja el catálogo por sucursal
  468.         return $this->redirectToRoute('cc_pedido_v2', ['id' => $id]);
  469.     }
  470.     // #[Route('/cabecera/{id}/favoritos', name: 'cc_favoritos')]
  471.     // public function favoritos(
  472.     //     ArticulosRepository $articulosRepository,
  473.     //     EstadisticasArticulosService $estadisticasService,
  474.     //     FavoritoscabRepository $favoritoscab,
  475.     //     Request $request,
  476.     //     int $id
  477.     // ): Response {
  478.     //     $cabecera = $this->doctrine
  479.     //         ->getRepository(Cabecera::class)
  480.     //         ->find($id);
  481.     //     if (!$cabecera) {
  482.     //         throw $this->createNotFoundException(
  483.     //             'Pedido no encontrado'
  484.     //         );
  485.     //     }
  486.     //     if ($cabecera->getIsFinalizada()) {
  487.     //         throw $this->createNotFoundException(
  488.     //             'Pedido finalizado'
  489.     //         );
  490.     //     }
  491.     //     $status = array('INICIADO', 'PROGRAMADO', 'EDICION');
  492.     //     if (!in_array($cabecera->getEstado(), $status)) {
  493.     //         throw $this->createNotFoundException(
  494.     //             'Este pedido no se puede editar'
  495.     //         );
  496.     //     }
  497.     //     //log
  498.     //     if ($cabecera->getEstado() == 'PROGRAMADO') {
  499.     //         $entityManager = $this->doctrine->getManager();
  500.     //         $status = $this->createStatus($cabecera, 'EDICION', $this->getUser());
  501.     //         $entityManager->persist($status);
  502.     //         $entityManager->flush();
  503.     //     }
  504.     //     //log
  505.     //     $favoritos = $favoritoscab->findAllByTerminal(10);
  506.     //     $sucursal = $this->doctrine
  507.     //         ->getRepository(Sucursal::class)
  508.     //         ->findOneBy(array('nombre' => $cabecera->getSucursal()));
  509.     //     $sucursal = $sucursal->getCodalmvent() ?? '';
  510.     //     $top_ids_articulos = $estadisticasService->obtenerIdsTopArticulos(
  511.     //         $cabecera->getNifcliente(),
  512.     //         $cabecera->getTelefonocliente(),
  513.     //     );
  514.     //     if(!empty($top_ids_articulos)){
  515.     //         $top_articulos = $estadisticasService->obtenerTopArticulos(
  516.     //             $top_ids_articulos,
  517.     //             $sucursal,
  518.     //         );
  519.     //     } else {
  520.     //         $top_articulos = [];
  521.     //     }
  522.     //     return $this->render('callcenter/pedido_v2.html.twig', [
  523.     //         'favoritos' => $favoritos,
  524.     //         'cabecera' => $cabecera,
  525.     //         'top' => $top_articulos,
  526.     //     ]);
  527.     // }
  528.     #[Route('/load-modal'name'load_modal'methods: ['GET'])]
  529.     public function loadModal(ArticulosRepository $articulosRepositoryRequest $request): Response
  530.     {
  531.         // Obtenemos el tipo de modal desde el request (en lugar de pasar directamente la plantilla)
  532.         $modalType $request->query->get('modalType''default');
  533.         $data = [];
  534.         // Definimos diferentes plantillas según el tipo de modal
  535.         switch ($modalType) {
  536.             case 'search':
  537.                 $template 'callcenter/search_modal.html.twig';
  538.                 break;
  539.             case 'top':
  540.                 // $top_articulos = $articulosRepository->findArticulosByFavorito(80098823, 'POBLADO');
  541.                 $template 'callcenter/top_modal.html.twig';
  542.                 break;
  543.             default:
  544.                 $template 'callcenter/default_modal.html.twig';
  545.         }
  546.         return $this->render($template$data);
  547.     }
  548.     // #[Route('/buscar-productos-modal', name: 'buscar_productos_modal', methods: ['GET'])]
  549.     // public function loadModal(): Response
  550.     // {
  551.     //     return $this->render('callcenter/search_modal.html.twig');
  552.     // }
  553.     #[Route('/buscar-productos'name'buscar_productos'methods: ['GET'])]
  554.     public function buscarProductos(ArticulosRepository $articulosRepositoryRequest $request): Response
  555.     {
  556.         $query $request->query->get('query');
  557.         $sucursal $this->doctrine
  558.             ->getRepository(Sucursal::class)
  559.             ->findOneBy(array('nombre' => $request->query->get('sucursal')));
  560.         $sucursal $sucursal->getCodalmvent() ?? '';
  561.         $articulos $articulosRepository->findArticulosByName($query$sucursal);
  562.         return $this->render('callcenter/search_results.html.twig', [
  563.             'articulos' => $articulos,
  564.             'query' => strtoupper($request->query->get('query')),
  565.         ]);
  566.     }
  567.     #[Route('/articulos'name'cc_articulos')]
  568.     public function articulos(ArticulosRepository $articulosRepositoryRequest $request): Response
  569.     {
  570.         // $template = $request->query->get('ajax') ? '_articulos.html.twig' : 'fav.html.twig';
  571.         $favorito $request->query->get('fav');
  572.         $sucursal $this->doctrine
  573.             ->getRepository(Sucursal::class)
  574.             ->findOneBy(array('nombre' => $request->query->get('sucursal')));
  575.         // $sucursal = $sucursal ? $sucursal->getCodalmvent() : '';
  576.         $sucursal $sucursal->getCodalmvent() ?? '';
  577.         $articulos $articulosRepository->findArticulosByFavorito($favorito$sucursal);
  578.         return $this->render('callcenter/_articulos.html.twig', [
  579.             'articulos' => $articulos,
  580.         ]);
  581.     }
  582.     #[Route('/articulo'name'cc_articulo')]
  583.     public function articulo(ArticulosRepository $articulosRepositoryRequest $request): Response
  584.     {
  585.         $id $request->query->get('codarticulo');
  586.         $fav $request->query->get('fav');
  587.         $articulo $articulosRepository->findArticulo($id$fav);
  588.         if (!$articulo) {
  589.             throw $this->createNotFoundException(
  590.                 'Artículo no encontrado'
  591.             );
  592.         }
  593.         $modsbyarticulo $articulosRepository->findModificadoresByArticulo($id);
  594.         $mods = array();
  595.         foreach ($modsbyarticulo as $item) {
  596.             $mods[] = $articulosRepository->findModificadores($item['codmodificador']);
  597.         }
  598.         $inicialstate $articulosRepository->validadorArticulos($modsbyarticulo);
  599.         return $this->render('callcenter/_articulo.html.twig', [
  600.             'articulo' => $articulo,
  601.             'modsbyarticulo' => $modsbyarticulo,
  602.             'mods' => $mods,
  603.             'jsonmodsbyarticulo' => json_encode($modsbyarticulo),
  604.             'jsonmods' => json_encode($mods),
  605.             'inicialstate' => $inicialstate,
  606.         ]);
  607.     }
  608.     #[Route('/crearlistas'name'cc_crearlistas')]
  609.     public function crearlistas(ArticulosRepository $articulosRepositoryModificadoreslinRepository $mlinRepositoryRequest $requestEntityManagerInterface $entityManager): response
  610.     {
  611.         $cabeceraId $request->query->get('cabecera');
  612.         $parentId $request->query->get('parent');
  613.         $q intval($request->query->get('q'));
  614.         $fav $request->query->get('fav');
  615.         $childs explode(","$request->query->get('childs'));
  616.         $modcabs explode(","$request->query->get('modcabs'));
  617.         $cabecera $entityManager->getRepository(Cabecera::class)->find($cabeceraId);
  618.         $parent $articulosRepository->findArticulo($parentId$fav);
  619.         // Crear línea principal y líneas hijas
  620.         $parentLine $this->createParentLine($cabecera$parent$q$fav);
  621.         $entityManager->persist($parentLine);
  622.         $childTotalPrice 0;
  623.         if (!empty($childs[0])) {
  624.             $childTotalPrice $this->createChildLines($childs$modcabs$parent$q$parentLine$mlinRepository$entityManager);
  625.         }
  626.         // Actualizar totales en línea principal y Cabecera
  627.         $this->updateParentLineTotal($parentLine$childTotalPrice);
  628.         $this->updateCabeceraTotals($cabecera$parentLine$childTotalPrice);
  629.         $entityManager->flush();
  630.         return $this->render('callcenter/_lineas.html.twig', [
  631.             'cabecera' => $cabecera,
  632.         ]);
  633.     }
  634.     private function createParentLine($cabecera$parent$q$fav): Lineas
  635.     {
  636.         $linePrice $parent['pneto'] * $q;
  637.         $line = new Lineas();
  638.         $line->setCabecera($cabecera);
  639.         $line->setCodarticulo($parent['codarticulo']);
  640.         $line->setDescripcion($parent['descripcion']);
  641.         $line->setPrecio($linePrice);
  642.         $line->setPreciounidad($parent['pneto']);
  643.         $line->setPreciototal($parent['pneto']);
  644.         $line->setUnidades($q);
  645.         $line->setCodfavoritos($fav);
  646.         $line->setCodImpuesto($parent['tipoiva']);
  647.         $parentPriceWithoutTax $this->calcularPrecioSinImpuesto($linePrice$line->getCodImpuesto());
  648.         $line->setPreciosiniva($parentPriceWithoutTax);
  649.         return $line;
  650.     }
  651.     private function createChildLines($childs$modcabs$parent$q$parentLine$mlinRepositoryEntityManagerInterface $entityManager): float
  652.     {
  653.         $parentLine->setNumlineasmodif(count($childs));
  654.         $childTotalPrice 0;
  655.         $childData = [];
  656.         foreach ($childs as $key => $child) {
  657.             $childArticle $mlinRepository->findModificador($child$parent['codarticulo'], $modcabs[$key]);
  658.             $linePrice $childArticle['incprecio'] * $q;
  659.             // Almacena toda la información relevante
  660.             $childData[] = [
  661.                 'childArticle' => $childArticle,
  662.                 'linePrice' => $linePrice,
  663.                 'quantity' => $q,
  664.             ];
  665.         }
  666.         usort($childData, function ($a$b) {
  667.             return $a['childArticle']['posicion'] - $b['childArticle']['posicion'];
  668.         });
  669.         foreach ($childData as $data) {
  670.             $childArticle $data['childArticle'];
  671.             $linePrice $data['linePrice'];
  672.             $q $data['quantity'];
  673.             $line = new Lineas();
  674.             $line->setCabecera($parentLine->getCabecera());
  675.             $line->setParent($parentLine);
  676.             $line->setCodarticulo($childArticle['codarticulocom']);
  677.             $line->setDescripcion($childArticle['descripcion']);
  678.             $line->setPrecio($linePrice);
  679.             $line->setUnidades($q);
  680.             $line->setNumlineasmodif(null);
  681.             $line->setCodImpuesto($childArticle['tipoiva']);
  682.             $line->setPreciosiniva($this->calcularPrecioSinImpuesto($linePrice$childArticle['tipoiva']));
  683.             $line->setPosicion($childArticle['posicion']);
  684.             $childTotalPrice += $linePrice;
  685.             $entityManager->persist($line);
  686.         }
  687.         // $entityManager->flush();
  688.         return $childTotalPrice;
  689.     }
  690.     private function updateParentLineTotal($parentLinefloat $childTotalPrice): void
  691.     {
  692.         // $parentLine->setPreciototal($parentLine->getPrecio() + $childTotalPrice);
  693.         $totalPrice $parentLine->getPrecio() + $childTotalPrice;
  694.         $parentLine->setPreciototal($totalPrice);
  695.         $parentPriceWithoutTax $this->calcularPrecioSinImpuesto($totalPrice$parentLine->getCodImpuesto());
  696.         $parentLine->setPreciosiniva($parentPriceWithoutTax);
  697.     }
  698.     private function updateCabeceraTotals($cabecera$parentLinefloat $childTotalPrice): void
  699.     {
  700.         $cabecera->setTotal($cabecera->getTotal() + $parentLine->getPrecio() + $childTotalPrice);
  701.         $cabecera->setTotalsiniva($cabecera->getTotalsiniva() + $parentLine->getPreciosiniva());
  702.         // $cabecera->setTotalsiniva($cabecera->getTotalsiniva() + $parentLine->getPreciosiniva() + $this->calcularPrecioSinImpuesto($childTotalPrice, $parentLine->getCodImpuesto()));
  703.     }
  704.     private function calcularPrecioSinImpuesto($precioConImpuesto$porcentajeImpuesto)
  705.     {
  706.         return $precioConImpuesto / (+ ($porcentajeImpuesto 100));
  707.     }
  708.     #[Route('/agregarcomentario/{parent}'name'cc_agregarcomentario')]
  709.     public function addComent(EntityManagerInterface $emLineasRepository $lRequest $requestint $parent): response
  710.     {
  711.         $p $l->findOneBy(['id' => $parent]);
  712.         $linea = new Lineas;
  713.         $form $this->createForm(LineasType::class, $linea);
  714.         $form->handleRequest($request);
  715.         if ($form->isSubmitted() && $form->isValid()) {
  716.             $linea $form->getData();
  717.             $linea->setCodarticulo(0);
  718.             $linea->setPrecio(0);
  719.             $linea->setCodfavoritos(0);
  720.             // $linea->setParent($p);
  721.             $linea->setCabecera($p->getCabecera());
  722.             $root $p->getRoot();
  723.             $n $root->getNumlineasmodif() + 1;
  724.             $root->setNumlineasmodif($n);
  725.             // $l->persistAsFirstChildOf($linea, $p);
  726.             $l->persistAsLastChildOf($linea$p);
  727.             $em->persist($root);
  728.             $em->flush();
  729.             // if($countComment > 0){
  730.             //     $l->moveUp($linea, $countComment);
  731.             // }
  732.             return $this->redirectToRoute('cc_favoritos', [
  733.                 'id' => $p->getCabecera()->getId(),
  734.             ]);
  735.         }
  736.         return $this->render('callcenter/_comentarios.html.twig', [
  737.             'form' => $form->createView(),
  738.             'parent' => $p
  739.         ]);
  740.     }
  741.     #[Route('/borrarlista/{id}'name'cc_borrarlista')]
  742.     public function borrarlista(LineasRepository $lRequest $requestint $id): response
  743.     {
  744.         $entityManager $this->doctrine->getManager();
  745.         // Linea que se quiere borrar
  746.         $linea $l->find($id);
  747.         if (!$linea) {
  748.             throw $this->createNotFoundException('Linea no encontrada.');
  749.         }
  750.         $cabecera $linea->getCabecera();
  751.         $precioTotal $linea->getPrecio();
  752.         $precioSinIVA $linea->getPreciosiniva();
  753.         if ($linea->getParent() === null && $linea->getNumlineasmodif() > 0) {
  754.             list($childPriceTotal$childPriceWithoutTax) = $this->removeChildLines($linea$l$entityManager);
  755.             $precioTotal += $childPriceTotal;
  756.             $precioSinIVA += $childPriceWithoutTax;
  757.         } elseif ($linea->getParent() !== null) {
  758.             $parentLine $linea->getRoot();
  759.             $parentLine->setNumlineasmodif($parentLine->getNumlineasmodif() - 1);
  760.             $parentLine->setPreciototal($parentLine->getPreciototal() - ($precioTotal $linea->getUnidades()));
  761.             $parentLine->setPreciosiniva($parentLine->getPreciosiniva() - $precioSinIVA); // Añadido para actualizar el preciosiniva del parent
  762.             $entityManager->persist($parentLine);
  763.         }
  764.         $cabecera->setTotal($cabecera->getTotal() - $precioTotal);
  765.         $cabecera->setTotalsiniva($cabecera->getTotalsiniva() - $precioSinIVA);
  766.         $entityManager->remove($linea);
  767.         $entityManager->persist($cabecera);
  768.         $entityManager->flush();
  769.         return $this->redirectToRoute('cc_favoritos', ['id' => $cabecera->getId()]);
  770.     }
  771.     private function removeChildLines(Lineas $parentLineLineasRepository $lEntityManagerInterface $entityManager): array
  772.     {
  773.         $childLines $l->findBy(['parent' => $parentLine->getId()]);
  774.         $childPriceTotal 0;
  775.         $childPriceWithoutTax 0;
  776.         foreach ($childLines as $child) {
  777.             $childPriceTotal += $child->getPrecio();
  778.             $childPriceWithoutTax += $child->getPreciosiniva();
  779.             $entityManager->remove($child);
  780.         }
  781.         return [$childPriceTotal$childPriceWithoutTax];
  782.     }
  783.     // #[Route('/borrarlista/{id}', name: 'cc_borrarlista')]
  784.     // public function borrarlista(LineasRepository $l, Request $request, int $id): response
  785.     // {
  786.     //     // $favoritos = $favoritoscab->findAllByTerminal(2);
  787.     //     $entityManager = $this->doctrine->getManager();
  788.     //     //linea que se quiere borrar
  789.     //     $linea = $this->doctrine
  790.     //         ->getRepository(Lineas::class)
  791.     //         ->find($id);
  792.     //     $cabecera = $linea->getCabecera();
  793.     //     $total = $cabecera->getTotal();
  794.     //     if ($linea->getParent() === null) {
  795.     //         if ($linea->getNumlineasmodif() > 0) {
  796.     //             $childs = $l->findby(['parent' => $linea->getId()]);
  797.     //             foreach ($childs as $key => $child) {
  798.     //                 $total = $total - $child->getPrecio();
  799.     //                 $entityManager->remove($child);
  800.     //             }
  801.     //         }
  802.     //     } else {
  803.     //         $p = $linea->getRoot();
  804.     //         $countChild = $l->childCount($linea);
  805.     //         $count = $countChild + 1;
  806.     //         $n = $p->getNumlineasmodif() - $count;
  807.     //         $p->setNumlineasmodif($n);
  808.     //         //probando
  809.     //         $p->setPreciototal($p->getPreciototal() - ($linea->getPrecio() / $linea->getUnidades()));
  810.     //         $entityManager->persist($p);
  811.     //     }
  812.     //     $total = $total - $linea->getPrecio();
  813.     //     $cabecera->setTotal($total);
  814.     //     $entityManager->remove($linea);
  815.     //     $entityManager->persist($cabecera);
  816.     //     $entityManager->flush();
  817.     //     return $this->redirectToRoute('cc_favoritos', array('id' => $linea->getCabecera()->getId()));
  818.     // }
  819.     #[Route('/enespera/{id?}'name'cc_enespera')]
  820.     public function esperarpago(?int $id null): response
  821.     {
  822.         $cabecera null;
  823.         if ($id) {
  824.             $cabecera $this->doctrine->getRepository(Cabecera::class)->find($id);
  825.         }
  826.         return $this->render('callcenter/enespera.html.twig', [
  827.             'cabecera' => $cabecera,
  828.         ]);
  829.     }
  830.     #[Route('/hacerpedido/{id}'name'cc_hacerpedido')]
  831.     public function generarxml(int $idXmlGeneratorService $xml): response
  832.     {
  833.         $cab $this->doctrine
  834.             ->getRepository(Cabecera::class)
  835.             ->find($id);
  836.         if ($cab->getIsFinalizada()) {
  837.             $this->addFlash('notice''Este pedido ya fue procesado anteriormente.');
  838.             if ($cab->getEstado() == 'EDICION') {
  839.                 $url $this->adminUrlGenerator
  840.                     ->setController(CabeceraCrudController::class)
  841.                     ->setAction(Action::DETAIL)
  842.                     ->setEntityId($cab->getId())
  843.                     ->generateUrl();
  844.                 return $this->redirect($url);
  845.             } else {
  846.                 return $this->render('callcenter/finalizarpedido.html.twig', [
  847.                     'cabecera' => $cab
  848.                 ]);
  849.             }
  850.         }
  851.         $estadoinicial $cab->getEstado();
  852.         $entityManager $this->doctrine->getManager();
  853.         if ($this->isReservation($cab) === false) {
  854.             $filename $xml->generatorXML($cab);
  855.             $cab->setFilename($filename);
  856.             $cab->setIsFinalizada(true);
  857.             $status $this->createStatus($cab'PROCESANDO'$this->getUser());
  858.         } else {
  859.             $cab->setIsFinalizada(false);
  860.             $status $this->createStatus($cab'PROGRAMADO'$this->getUser());
  861.         }
  862.         $entityManager->persist($status);
  863.         $entityManager->persist($cab);
  864.         $entityManager->flush();
  865.         if ($estadoinicial == 'EDICION') {
  866.             $url $this->adminUrlGenerator
  867.                 ->setController(CabeceraCrudController::class)
  868.                 ->setAction(Action::DETAIL)
  869.                 ->setEntityId($cab->getId())
  870.                 ->generateUrl();
  871.             return $this->redirect($url);
  872.         } else {
  873.             return $this->render('callcenter/finalizarpedido.html.twig', [
  874.                 'cabecera' => $cab
  875.             ]);
  876.         }
  877.     }
  878.     // #[Route('/hacerpedido/{id}', name: 'cc_hacerpedido')]
  879.     // public function generarxml(int $id, Xml $xml): response
  880.     // {
  881.     //     $cab = $this->doctrine
  882.     //         ->getRepository(Cabecera::class)
  883.     //         ->find($id);
  884.     //     $estadoinicial = $cab->getEstado();
  885.     //     if ($this->isReservation($cab) === false) {
  886.     //         $datetime['fecha'] = $cab->getUpdatedAt()->format('dm');
  887.     //         $datetime['hora'] = $cab->getUpdatedAt()->format('His');
  888.     //         $filename = substr($cab->getSucursal(), 0, 3) . $datetime['fecha'] . $datetime['hora'] . '-' . $cab->getId();
  889.     //         $cab->setFilename($filename);
  890.     //         $cab->setIsFinalizada(true);
  891.     //         $entityManager = $this->doctrine->getManager();
  892.     //         //log
  893.     //         $status = $this->createStatus($cab, 'PROCESANDO', $this->getUser());
  894.     //         $entityManager->persist($status);
  895.     //         //log
  896.     //         $entityManager->persist($cab);
  897.     //         $numlineas = 2;
  898.     //         foreach ($cab->getLineas() as $key => $linea) {
  899.     //             if ($linea->getParent() == null) {
  900.     //                 $numlineas++;
  901.     //             }
  902.     //         }
  903.     //         $xmlText = $xml->generarXml($cab, $datetime, $numlineas, $filename);
  904.     //         // SIRVE PARA GUARDAR EL ARCHIVO EN PUBLIC/UPLOADS*****
  905.     //         $filenameext = $filename . '.xml';
  906.     //         $path1 = $this->getParameter('kernel.project_dir') . '/public/uploads/' . $filenameext;
  907.     //         $path2 = $this->getParameter('kernel.project_dir') . '/public/respaldoXML/' . $filenameext;
  908.     //         $fileSystem = new Filesystem();
  909.     //         $fileSystem->dumpFile($path1, $xmlText);
  910.     //         $fileSystem->dumpFile($path2, $xmlText);
  911.     //     } else {
  912.     //         $cab->setIsFinalizada(false);
  913.     //         $entityManager = $this->doctrine->getManager();
  914.     //         //log
  915.     //         $status = $this->createStatus($cab, 'PROGRAMADO', $this->getUser());
  916.     //         $entityManager->persist($status);
  917.     //         //log
  918.     //         $entityManager->persist($cab);
  919.     //     }
  920.     //     $entityManager->flush();
  921.     //     if ($estadoinicial == 'EDICION') {
  922.     //         $url = $this->adminUrlGenerator
  923.     //             ->setController(CabeceraCrudController::class)
  924.     //             ->setAction(Action::DETAIL)
  925.     //             ->setEntityId($cab->getId())
  926.     //             ->generateUrl();
  927.     //         return $this->redirect($url);
  928.     //     } else {
  929.     //         return $this->render('callcenter/finalizarpedido.html.twig', [
  930.     //             'cabecera' => $cab
  931.     //         ]);
  932.     //     }
  933.     // }
  934.     #[Route('/confirmarpedido/{id}'name'cc_confirmarpedido')]
  935.     public function confirmarpedido(int $idRequest $requestGlobalPayService $globalPayService): response
  936.     {
  937.         $cab $this->doctrine
  938.             ->getRepository(Cabecera::class)
  939.             ->find($id);
  940.         // Validar que el pedido tenga al menos un producto
  941.         // Solo contamos líneas principales (sin parent) que no sean domicilio (codarticulo != '0')
  942.         $lineasProducto $cab->getLineas()->filter(function($linea) {
  943.             return $linea->getParent() === null && $linea->getCodarticulo() !== '0';
  944.         });
  945.         if ($lineasProducto->count() === 0) {
  946.             $this->addFlash('error''No puede confirmar un pedido sin artículos. Por favor agregue al menos un producto.');
  947.             return $this->redirectToRoute('cc_pedido_v2', ['id' => $id]);
  948.         }
  949.         $form $this->createForm(Cabecera2Type::class, $cab);
  950.         $form->handleRequest($request);
  951.         if ($form->isSubmitted() && $form->isValid()) {
  952.             $cab $form->getData();
  953.             $propinatotal $cab->getPropinatotal();
  954.             if (is_numeric($propinatotal) && $propinatotal 0) {
  955.                 $cab->setPropinatotal(floor($propinatotal 100) * 100);
  956.             } else {
  957.                 $cab->setPropinatotal(0);
  958.                 $cab->setPropinaporcentaje(0);
  959.             }
  960.             if ((int) $cab->getMetododepago() === (int) Cabecera::PAY_METHOD['CALL CENTER PREPAGADA']) {
  961.                 $data $globalPayService->prepareGlobalpayData([
  962.                     'nifcliente' => $cab->getNifcliente(),
  963.                     'emailcliente' => $cab->getEmailLinkdepago(),
  964.                     'nombres' => $cab->getNombres(),
  965.                     'apellidos' => ($cab->getApellidos() === null or $cab->getApellidos() === '') ? '_' $cab->getApellidos(),
  966.                     'id' => $cab->getId(),
  967.                     'total' => $cab->getTotal() + $cab->getPropinatotal(),
  968.                     'totalsiniva' => $cab->getTotalsiniva(),
  969.                     'sucursal' => $cab->getSucursal(),
  970.                 ]);
  971.                 $response $globalPayService->enviarDatos($data);
  972.                 $content json_decode($response['content'], true);
  973.                 $cab->setLinkdepago($content['data']['payment']['payment_url']);
  974.                 $entityManager $this->doctrine->getManager();
  975.                 $entityManager->persist($cab);
  976.                 $entityManager->flush();
  977.                 return $this->redirectToRoute('cc_linkdepago', [
  978.                     'id' => $cab->getId()
  979.                 ]);
  980.             }
  981.             $entityManager $this->doctrine->getManager();
  982.             $entityManager->persist($cab);
  983.             $entityManager->flush();
  984.             // CAMBIO: Ahora usamos ConectorPlus en lugar del flujo XML antiguo
  985.             // Redirigir al nuevo flujo con ConectorPlus en OrderController
  986.             return $this->redirectToRoute('cc_procesar_pedido_confirmado', [
  987.                 'id' => $cab->getId()
  988.             ]);
  989.             // CÓDIGO ANTIGUO (mantener para rollback):
  990.             // return $this->redirectToRoute('cc_hacerpedido', [
  991.             //     'id' => $cab->getId()
  992.             // ]);
  993.         }
  994.         return $this->render('callcenter/confirmarpedido.html.twig', [
  995.             'cabecera' => $cab,
  996.             'form' => $form->createView(),
  997.         ]);
  998.     }
  999.     #[Route('/linkdepago/{id}'name'cc_linkdepago')]
  1000.     public function linkdepago(int $idRequest $requestMailerService $mailerService): response
  1001.     {
  1002.         $this->logger->info('=== INICIO linkdepago ===', [
  1003.             'id' => $id,
  1004.             'method' => $request->getMethod(),
  1005.             'is_submitted' => $request->isMethod('POST')
  1006.         ]);
  1007.         $entityManager $this->doctrine->getManager();
  1008.         $cabecera $entityManager->getRepository(Cabecera::class)->find($id);
  1009.         if (!$cabecera) {
  1010.             // Manejar el caso de que la cabecera no se encuentre
  1011.             $this->logger->error('Cabecera no encontrada', ['id' => $id]);
  1012.             $this->addFlash('error''No se encontró el pedido solicitado.');
  1013.             return $this->redirectToRoute('call_center');
  1014.         }
  1015.         if ($cabecera->getEmailLinkdepago() === null) {
  1016.             $cabecera->setEmailLinkdepago($cabecera->getEmailcliente() ?? '');
  1017.         }
  1018.         // $estado = $entityManager->getRepository(CabeceraLinkdepago::class)->findOneBy(
  1019.         //     ['Cabecera' => $cabecera->getId()],
  1020.         //     ['createdAt' => 'DESC']
  1021.         // );
  1022.         $form $this->createForm(CabeceraEmailLinkdepagoType::class, $cabecera);
  1023.         $form->handleRequest($request);
  1024.         if ($form->isSubmitted() && $form->isValid()) {
  1025.             $this->logger->info('Formulario enviado y válido', [
  1026.                 'cabecera_id' => $cabecera->getId(),
  1027.                 'email_destino' => $cabecera->getEmailLinkdepago()
  1028.             ]);
  1029.             $config $entityManager->getRepository(Configuracion::class)->findOneBy([]);
  1030.             if (!$config) {
  1031.                 $this->logger->error('No se encontró configuración de correo en la base de datos');
  1032.                 $this->addFlash('error''No se encontró la configuración de correo. Por favor contacte al administrador.');
  1033.                 // Redirigir para preservar el flash message
  1034.                 return $this->redirectToRoute('cc_linkdepago', ['id' => $id]);
  1035.                 // CÓDIGO ANTERIOR (comentado):
  1036.                 // return $this->render('callcenter/linkdepago.html.twig', [
  1037.                 //     'cabecera' => $cabecera,
  1038.                 //     'estado' => null,
  1039.                 //     'form' => $form->createView(),
  1040.                 // ]);
  1041.             }
  1042.             $this->logger->info('Configuración de correo encontrada', [
  1043.                 'mail_host' => $config->getMailHost(),
  1044.                 'mail_puerto' => $config->getMailPuerto(),
  1045.                 'mail_usuario' => $config->getMailUsuario(),
  1046.             ]);
  1047.             try {
  1048.                 $this->logger->info('Iniciando envío de correo...', [
  1049.                     'destinatario' => $cabecera->getEmailLinkdepago(),
  1050.                     'cabecera_id' => $cabecera->getId(),
  1051.                     'link_pago' => $cabecera->getLinkdepago()
  1052.                 ]);
  1053.                 $mailerService->sendEmail(
  1054.                     $cabecera->getEmailLinkdepago(),
  1055.                     "Crepes & Waffles - Tu link de pago seguro",
  1056.                     "emails/linkdepago.html.twig",
  1057.                     ['cabecera' => $cabecera'timeout' => $config->getLinkdepagoTimeout() ?? 5],
  1058.                 );
  1059.                 $this->logger->info('Correo enviado exitosamente', [
  1060.                     'destinatario' => $cabecera->getEmailLinkdepago(),
  1061.                     'cabecera_id' => $cabecera->getId()
  1062.                 ]);
  1063.             } catch (\Exception $e) {
  1064.                 $this->logger->error('Error al enviar correo', [
  1065.                     'error_message' => $e->getMessage(),
  1066.                     'error_code' => $e->getCode(),
  1067.                     'error_file' => $e->getFile(),
  1068.                     'error_line' => $e->getLine(),
  1069.                     'trace' => $e->getTraceAsString(),
  1070.                     'destinatario' => $cabecera->getEmailLinkdepago(),
  1071.                     'cabecera_id' => $cabecera->getId()
  1072.                 ]);
  1073.                 $this->addFlash('error''No se pudo enviar el correo: ' $e->getMessage());
  1074.                 // CAMBIO: Usar patrón Post-Redirect-Get en lugar de render directo
  1075.                 // Los flash messages se preservan automáticamente en redirecciones
  1076.                 // Esto evita que se pierdan los mensajes y previene reenvío del formulario
  1077.                 return $this->redirectToRoute('cc_linkdepago', ['id' => $id]);
  1078.                 // CÓDIGO ANTERIOR (comentado - causaba pérdida de flash messages):
  1079.                 // return $this->render('callcenter/linkdepago.html.twig', [
  1080.                 //     'cabecera' => $cabecera,
  1081.                 //     'estado' => null,
  1082.                 //     'form' => $form->createView(),
  1083.                 // ]);
  1084.             }
  1085.             $cabecera $form->getData();
  1086.             $entityManager->persist($cabecera);
  1087.             $entityManager->flush();
  1088.             $this->logger->info('Flush completado, redirigiendo a cc_enespera', [
  1089.                 'cabecera_id' => $cabecera->getId()
  1090.             ]);
  1091.             $this->addFlash('success''El correo se envió correctamente.');
  1092.             // Pasar el ID para mostrar el mensaje correcto en la página de confirmación
  1093.             return $this->redirectToRoute('cc_enespera', ['id' => $cabecera->getId()]);
  1094.         }
  1095.         $this->logger->info('Mostrando formulario (no enviado o inválido)', [
  1096.             'is_submitted' => $form->isSubmitted(),
  1097.             'is_valid' => $form->isSubmitted() ? $form->isValid() : 'N/A'
  1098.         ]);
  1099.         return $this->render('callcenter/linkdepago.html.twig', [
  1100.             'cabecera' => $cabecera,
  1101.             // 'estado' => $estado,
  1102.             'estado' => null,
  1103.             'form' => $form->createView(),
  1104.         ]);
  1105.     }
  1106.     private function isReservation(Cabecera $cabecera): bool
  1107.     {
  1108.         if ($cabecera->getFechareserva() != null) {
  1109.             //fecha actual mas el tiempo de preparacion
  1110.             if ($cabecera->getTipodeservicio() ==  16) {
  1111.                 $paramtimebc $this->getParameter('app.bc.horaclienterecoge');
  1112.             } else {
  1113.                 $paramtimebc $this->getParameter('app.bc.horareserva');
  1114.             }
  1115.             $time date("Y-m-d H:i:s"strtotime($paramtimebc ' minutes'));
  1116.             //Si la fecha de reserva es mayor que $time, Sí es reserva
  1117.             if ($cabecera->getFechareserva()->format('Y-m-d H:i:s') > $time) {
  1118.                 // Es reserva
  1119.                 return true;
  1120.             } else {
  1121.                 // No es reserva
  1122.                 return false;
  1123.             }
  1124.         } else {
  1125.             return false;
  1126.         }
  1127.     }
  1128.     #[Route('/cambiarestado/{id}/{action}'name'cambiar_estado')]
  1129.     public function cambiarEstado(int $id$action)
  1130.     {
  1131.         $cab $this->doctrine
  1132.             ->getRepository(Cabecera::class)
  1133.             ->find($id);
  1134.         if (!$cab) {
  1135.             throw $this->createNotFoundException(
  1136.                 'Pedido no encontrado'
  1137.             );
  1138.         }
  1139.         $entityManager $this->doctrine->getManager();
  1140.         switch ($action) {
  1141.             case 'cancelar':
  1142.                 $status $this->createStatus($cab'CANCELADO'$this->getUser());
  1143.                 $flash 'Pedido Cancelado';
  1144.                 $cab->setIsFinalizada(true);
  1145.                 $cab->setLinkdepago(null);
  1146.                 $entityManager->persist($cab);
  1147.                 break;
  1148.             case 'anular':
  1149.                 $status $this->createStatus($cab'ANULADO'$this->getUser());
  1150.                 $flash 'Pedido anulado';
  1151.                 $cab->setLinkdepago(null);
  1152.                 $entityManager->persist($cab);
  1153.                 break;
  1154.         }
  1155.         $entityManager->persist($status);
  1156.         $entityManager->flush();
  1157.         $url $this->adminUrlGenerator
  1158.             ->setController(CabeceraCrudController::class)
  1159.             ->setAction(Action::DETAIL)
  1160.             ->setEntityId($id)
  1161.             ->removeReferrer()
  1162.             ->generateUrl();
  1163.         $this->addFlash('success'$flash);
  1164.         return $this->redirect($url);
  1165.     }
  1166. }
  1167. // $ppk = $this->getParameter('kernel.project_dir') . '/public/uploads/idisftp.ppk';
  1168. // $key = PublicKeyLoader::load(file_get_contents($ppk), $password = false);
  1169. // $sftp = new SFTP('64.76.58.172', 222);
  1170. // $sftp_login = $sftp->login('idisftp', $key);
  1171. // if($sftp_login) {
  1172. //     // return $this->render('default/test.html.twig', array(
  1173. //     // 'path' => $sftp->exec('pwd'),
  1174. //     // ));
  1175. //     // $sftp->enablePTY();
  1176. //     dd($sftp->nlist());
  1177. //     dd($sftp->put('filename.remote', 'xxx'));
  1178. // }
  1179. // else throw new \Exception('Cannot login into your server !');