src/Controller/Admin/OperacionAdminController.php line 79

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller\Admin;
  4. use App\DTO\CancelOperacionDTO;
  5. use App\DTO\FinishOperacionDTO;
  6. use App\DTO\SettleOperacionDTO;
  7. use App\Entity\AccionEstado;
  8. use App\Entity\Operacion;
  9. use App\Entity\PlantillaContrato;
  10. use App\Enum\EstadoRelojEnum;
  11. use App\Exception\AsentadaOperacionException;
  12. use App\Exception\BorradoOperacionException;
  13. use App\Exception\CanceladaOperacionException;
  14. use App\Exception\ConfirmadaOperacionException;
  15. use App\Exception\ContractOperacionException;
  16. use App\Exception\DeliveryOperacionException;
  17. use App\Exception\EmptyOperacionException;
  18. use App\Exception\EnTramitacionOperacionException;
  19. use App\Exception\FinalizadaOperacionException;
  20. use App\Exception\RenderWrapperException;
  21. use App\Exception\TramitadaOperacionException;
  22. use App\Service\NumberToWords\NumberToWordsService;
  23. use App\Service\Renders\RenderWrapperService;
  24. use App\UseCase\Operacion\AsentadaUseCase;
  25. use App\UseCase\Operacion\BorradoUseCase;
  26. use App\UseCase\Operacion\CanceladaUseCase;
  27. use App\UseCase\Operacion\CancelarRelojUseCase;
  28. use App\UseCase\Operacion\ConfirmarOperacionUseCase;
  29. use App\UseCase\Operacion\EnTramitacionUseCase;
  30. use App\UseCase\Operacion\FinalizadaUseCase;
  31. use App\UseCase\Operacion\TramitarOperacionUseCase;
  32. use Doctrine\Persistence\ManagerRegistry;
  33. use Exception;
  34. use InvalidArgumentException;
  35. use Sonata\AdminBundle\Controller\CRUDController;
  36. use Symfony\Component\HttpFoundation\File\UploadedFile;
  37. use Symfony\Component\HttpFoundation\Request;
  38. use Symfony\Component\HttpFoundation\RequestStack;
  39. use Symfony\Component\HttpFoundation\Response;
  40. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  41. use Symfony\Component\HttpKernel\KernelInterface;
  42. use Symfony\Component\Routing\Generator\UrlGenerator;
  43. use Vich\UploaderBundle\Storage\StorageInterface;
  44. final class OperacionAdminController extends CRUDController
  45. {
  46.     protected $om;
  47.     private $cacheDir;
  48.     private $tmpDir;
  49.     private $locale;
  50.     public function __construct(
  51.         KernelInterface $kernel,
  52.         ManagerRegistry $mr,
  53.         private EnTramitacionUseCase $useCaseEnTramitacionOperacion,
  54.         private TramitarOperacionUseCase $useCaseTramitarOperacion,
  55.         private ConfirmarOperacionUseCase $useCaseConfirmarOperacion,
  56.         private AsentadaUseCase $useCaseAsentadaOperacion,
  57.         private FinalizadaUseCase $useCaseFinalizadaOperacion,
  58.         private CanceladaUseCase $useCaseCanceladaOperacion,
  59.         private CancelarRelojUseCase $useCaseCancelarReloj,
  60.         private BorradoUseCase $useCaseBorradoOperacion,
  61.         private RenderWrapperService $renderWrapper,
  62.         private NumberToWordsService $numberToWords,
  63.         private StorageInterface $storage,
  64.         private RequestStack $requestStack
  65.     )
  66.     {
  67.         $this->om $mr->getManager();
  68.         $this->cacheDir $kernel->getCacheDir();
  69.         $this->tmpDir $kernel->getCacheDir().DIRECTORY_SEPARATOR."tmp"//$kernel->getProjectDir()."\\var\\tmp";
  70.         $this->locale $this->requestStack->getCurrentRequest()->getLocale()??$_ENV['LOCALE'];
  71.     }
  72.     public function editAction(Request $request): Response
  73.     {
  74.         $responseEdit parent::editAction($request);
  75.         try {
  76.             switch ($request->query->get('action'))
  77.             {
  78.                 case 'processed':
  79.                     return $this->processedAction($request);
  80.                 case 'contract':
  81.                     return $this->contractAction($request);
  82.                 case 'confirmed':
  83.                     return $this->confirmedAction($request);
  84.                 case 'settle':
  85.                     return $this->settleAction($request);
  86.                 case 'finish':
  87.                     return $this->finishAction($request);
  88.                 case 'cancel':
  89.                     return $this->cancelAction($request);
  90.                 default:
  91.                     return $responseEdit;
  92.             }
  93.         }
  94.         catch (EmptyOperacionException $e)
  95.         {
  96.             $this->addFlash('error'$this->trans($e->getMessage(), [], 'exception'));
  97.         }
  98.         return $this->redirect($_SERVER['HTTP_REFERER']);
  99.     }
  100.     public function contractAction(Request $request)
  101.     {
  102.         try {
  103.             $content '';
  104.             $existingObject $this->assertObjectExists($requesttrue);
  105.             if(!$existingObject) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  106.             $idioma mb_strtolower($existingObject->getIdioma()??$this->locale);
  107.             $tipo mb_strtolower($existingObject->getTipo());
  108.             $empresa mb_strtolower($existingObject->getUnidadNegocio()?->getEmpresa()?->getCod());
  109.             $templateName $empresa "plantilla_contrato.$empresa.$tipo.$idioma.all.html.twig" "plantilla_contrato.$tipo.$idioma.all.html.twig";
  110.             $template $this->om->getRepository(PlantillaContrato::class)->findOneByFilename($templateName);
  111.             if(!$template) throw new ContractOperacionException("la plantilla [$templateName] no existe");
  112.             switch ($request->get('format'))
  113.             {
  114.                 case 'word':
  115.                     $filename date('ymd')."-Contrato-$tipo.doc";
  116.                     $mime 'application/msword';
  117.                     $templateName .= 'w';
  118.                     break;
  119.                 case 'pdf':
  120.                     $filename date('ymd')."-Contrato-$tipo.pdf";
  121.                     $mime 'application/pdf';
  122.                     break;
  123.                 default:
  124.                     throw new ContractOperacionException('formato solicitado incorrecto ['.$request->get('format').']');
  125.                     break;
  126.             }
  127.             if($template->getTemplate())
  128.             {
  129.                 $filenamePath $this->storage->resolvePath($template'templateFile');
  130.                 $templateFile = ($filenamePath && file_exists($filenamePath)) ? new UploadedFile($filenamePath$template->getTemplate(), 'image'nulltrue) : null;
  131.                 if(!$templateFile) throw new ContractOperacionException("No se ha podido acceder a la plantilla $filenamePath");
  132.                 $precioPagarStr is_null($existingObject?->getPrecioPagar()) ? null $this->numberToWords->converter(abs($existingObject->getPrecioPagar()), $existingObject->getIdioma());
  133.                 $content = ($this->renderWrapper)($template->getTemplate(), [
  134.                     'operacion' => $existingObject,
  135.                     'operacion.precioPagarStr' => $precioPagarStr,
  136.                     'firma' => $existingObject?->getFirmante() ,
  137.                     'segments' => [
  138.                         'DetalleVenta' => $existingObject->getVenta()?->getDetalle(),
  139.                         'DetalleCompra' => $existingObject->getCompra()?->getDetalle(),
  140.                     ],
  141.                     'templateFile' => $templateFile,
  142.                     'format' => $request->get('format')
  143.                 ]);
  144.                 $mime 'application/vnd.oasis.opendocument.text';
  145.             }
  146.             else if($template->getSource()) {
  147.                 $content = ($this->renderWrapper)($templateName, [
  148.                     'operacion' => $existingObject,
  149.                     'plantilla' => $template,
  150.                     'source' => $template->getSource(),
  151.                     'header' => $template->getHeader(),
  152.                     'footer' => $template->getfooter(),
  153.                     'format' => $request->get('format')
  154.                 ]);
  155.             }
  156.             $response = new Response($content);
  157.             $response->headers->set('Content-Type'$mime);
  158.             $response->headers->set('Content-Disposition''attachment; filename="'.$filename.'"');
  159.             $response->headers->set('Content-Length'strlen($content??''));
  160.             $response->headers->set('Pragma''no-cache');
  161.             $response->headers->set('Cache-Control''no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
  162.             $response->headers->set('Expires''0');
  163.             return $response;
  164.         }
  165.         catch (NotFoundHttpException $e)
  166.         {
  167.             $this->addFlash('sonata_flash_error'$e->getMessage());
  168.         }
  169.         catch (ContractOperacionException $e)
  170.         {
  171.             $this->addFlash('sonata_flash_error'$e->getMessage());
  172.         }
  173.         catch(RenderWrapperException $e)
  174.         {
  175.             $this->addFlash('sonata_flash_error'$e->getMessage());
  176.         }
  177.         catch(Exception $e)
  178.         {
  179.             $this->addFlash('sonata_flash_error'$e->getMessage());
  180.         }
  181.         return $this->redirect($_SERVER['HTTP_REFERER']);
  182.     }
  183.     public function deliveryAction(Request $request)
  184.     {
  185.         try {
  186.             $content '';
  187.             $existingObject $this->assertObjectExists($requesttrue);
  188.             if(!$existingObject) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  189.             $detalleVentaReloj $existingObject->getVenta()->getDetalle()->filter(fn($dv) => $dv->getReloj()->getId() == $request->get('reloj'))->first();
  190.             if (!$detalleVentaReloj)  throw new DeliveryOperacionException('Detalle de venta no encontrado para el reloj indicado.');
  191.             $reloj $detalleVentaReloj->getReloj();
  192.             $idioma mb_strtolower($existingObject->getIdioma()??$this->locale);
  193.             $empresa mb_strtolower($existingObject->getUnidadNegocio()?->getEmpresa()?->getCod());
  194.             $templateName $empresa "plantilla_delivery.$empresa.$idioma.all.html.twig" "plantilla_delivery.$idioma.all.html.twig";
  195.             $template $this->om->getRepository(PlantillaContrato::class)->findOneByFilename($templateName);
  196.             if(!$template) throw new DeliveryOperacionException("la plantilla [$templateName] no existe");
  197.             $filename date('ymd').'-Delivery-'.$reloj->getCodigo().'.docx';
  198.             //$mime = 'application/msword';
  199.             $mime 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
  200.             if($template->getTemplate())
  201.             {
  202.                 $filenamePath $this->storage->resolvePath($template'templateFile');
  203.                 $templateFile $this->cacheDirDIRECTORY_SEPARATOR uniqid('delivery_'true) . '.odt';
  204.                 if (!is_readable($filenamePath)) {
  205.                     throw new DeliveryOperacionException("No se puede leer el archivo $filenamePath");
  206.                 }
  207.                 if (!is_writable(dirname($templateFile))) {
  208.                     throw new DeliveryOperacionException("No se puede escribir en el directorio " dirname($templateFile));
  209.                 }
  210.                 if(!copy($filenamePath$templateFile)) throw new DeliveryOperacionException("No se ha podido cpiar la plantilla $filenamePath a $templateFile");
  211.                 //$templateFile = ($filenamePath && file_exists($filenamePath)) ? new UploadedFile($filenamePath, $template->getTemplate(), $mime, null, true) : null;
  212.                 if(!file_exists($templateFile)) throw new DeliveryOperacionException("No se ha podido acceder a la plantilla $filenamePath");
  213.                 $content = ($this->renderWrapper)($template->getTemplate(), [
  214.                     'operacion' => $existingObject,
  215.                     'detallereloj' => $detalleVentaReloj,
  216.                     'destinatarioEnvio' => $detalleVentaReloj->getVenta()->getDestinatarioEnvio(),
  217.                     'direccionEnvio' => $detalleVentaReloj->getVenta()->getDireccionEnvio(),
  218.                     'relojFechaEnvio' => $detalleVentaReloj->getFechaEnvio()?->format('d/m/Y'),
  219.                     'relojMarca' => $reloj->getMarca(),
  220.                     'relojFecha' => $reloj->getFecha()?->format('d/m/Y'),
  221.                     'relojCaja' => $reloj->getCaja() ? 'SI''NO',
  222.                     'relojPapeles' => $reloj->getPapeles() ? 'SI' 'NO',
  223.                     'relojGarantia' => $detalleVentaReloj->getGarantiaStr(),
  224.                     'relojGarantiaFecha' => $detalleVentaReloj->getGarantiaFecha()?->format('d/m/Y'),
  225.                     'relojRecompra' => $detalleVentaReloj->getRecompraStr(),
  226.                     'relojRecompraIndice' => $detalleVentaReloj->getRecompraIndice(),
  227.                     'relojRecompraFechaStr' => $detalleVentaReloj->getRecompraFechaStr(),
  228.                     'relojRecompraFecha' => $detalleVentaReloj->getRecompraFecha()?->format('d/m/Y'),
  229.                     'templateFile' => $templateFile,
  230.                     'format' => 'docx'
  231.                 ]);
  232.                 //$mime = 'application/vnd.oasis.opendocument.text';
  233.             }
  234.             else if($template->getSource()) {
  235.                 $content = ($this->renderWrapper)($templateName, [
  236.                     'operacion' => $existingObject,
  237.                     'plantilla' => $template,
  238.                     'source' => $template->getSource(),
  239.                     'header' => $template->getHeader(),
  240.                     'footer' => $template->getfooter(),
  241.                     'format' => $request->get('format')
  242.                 ]);
  243.             }
  244.             $response = new Response($content);
  245.             $response->headers->set('Content-Type'$mime);
  246.             $response->headers->set('Content-Disposition''attachment; filename="'.$filename.'"');
  247.             $response->headers->set('Content-Length'strlen($content??''));
  248.             $response->headers->set('Pragma''no-cache');
  249.             $response->headers->set('Cache-Control''no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
  250.             $response->headers->set('Expires''0');
  251.             if (file_exists($templateFile)) {
  252.                 unlink($templateFile);
  253.             }
  254.             return $response;
  255.         }
  256.         catch (NotFoundHttpException $e)
  257.         {
  258.             $this->addFlash('sonata_flash_error'$e->getMessage());
  259.         }
  260.         catch (DeliveryOperacionException $e)
  261.         {
  262.             $this->addFlash('sonata_flash_error'$e->getMessage());
  263.         }
  264.         catch(RenderWrapperException $e)
  265.         {
  266.             $this->addFlash('sonata_flash_error'$e->getMessage());
  267.         }
  268.         catch(Exception $e)
  269.         {
  270.             $this->addFlash('sonata_flash_error'$e->getMessage());
  271.         }
  272.         return $this->redirect($_SERVER['HTTP_REFERER']);
  273.     }
  274.     public function proformaAction(Request $request)
  275.     {
  276.         try {
  277.             $content '';
  278.             $existingObject $this->assertObjectExists($requesttrue);
  279.             if(!$existingObject) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  280.             $detalleVentaReloj $existingObject->getVenta()->getDetalle()->filter(fn($dv) => $dv->getReloj()->getId() == $request->get('reloj'))->first();
  281.             $reloj $detalleVentaReloj->getReloj();
  282.             $idioma mb_strtolower($existingObject->getIdioma()??$this->locale);
  283.             $empresa mb_strtolower($existingObject->getUnidadNegocio()?->getEmpresa()?->getCod());
  284.             $templateName $empresa "plantilla_proforma.$empresa.$idioma.all.html.twig" "plantilla_proforma.$idioma.all.html.twig";
  285.             $template $this->om->getRepository(PlantillaContrato::class)->findOneByFilename($templateName);
  286.             if(!$template) throw new DeliveryOperacionException("la plantilla [$templateName] no existe");
  287.             $filename date('ymd').'-Proforma-'.$reloj->getCodigo().'.xls';
  288.             $mime 'application/vnd.ms-excel';
  289.             if($template->getTemplate())
  290.             {
  291.                 $filenamePath $this->storage->resolvePath($template'templateFile');
  292.                 $templateFile = ($filenamePath && file_exists($filenamePath)) ? new UploadedFile($filenamePath$template->getTemplate(), 'image'nulltrue) : null;
  293.                 if(!$templateFile) throw new DeliveryOperacionException("No se ha podido acceder a la plantilla $filenamePath");
  294.                 //fecha es la del estado en tramitación
  295.                 //En la descripción, concatena: Marca + espacio + Modelo 1 + espacio + Modelo 2 + coma y espacio + “Ref.” + Referencia 1 + Referencia 2 (sin espacio en medio)
  296.                 $content = ($this->renderWrapper)($template->getTemplate(), [
  297.                     'operacion' => $existingObject,
  298.                     'reloj' => $reloj,
  299.                     'templateFile' => $templateFile,
  300.                     'format' => 'excel'
  301.                 ]);
  302.                 $mime 'application/vnd.oasis.opendocument.spreadsheet';
  303.             }
  304.             else if($template->getSource()) {
  305.                 $content = ($this->renderWrapper)($templateName, [
  306.                     'operacion' => $existingObject,
  307.                     'plantilla' => $template,
  308.                     'source' => $template->getSource(),
  309.                     'header' => $template->getHeader(),
  310.                     'footer' => $template->getfooter(),
  311.                     'format' => $request->get('format')
  312.                 ]);
  313.             }
  314.             $response = new Response($content);
  315.             $response->headers->set('Content-Type'$mime);
  316.             $response->headers->set('Content-Disposition''attachment; filename="'.$filename.'"');
  317.             $response->headers->set('Content-Length'strlen($content??''));
  318.             $response->headers->set('Pragma''no-cache');
  319.             $response->headers->set('Cache-Control''no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
  320.             $response->headers->set('Expires''0');
  321.             return $response;
  322.         }
  323.         catch (NotFoundHttpException $e)
  324.         {
  325.             $this->addFlash('sonata_flash_error'$e->getMessage());
  326.         }
  327.         catch (DeliveryOperacionException $e)
  328.         {
  329.             $this->addFlash('sonata_flash_error'$e->getMessage());
  330.         }
  331.         catch(RenderWrapperException $e)
  332.         {
  333.             $this->addFlash('sonata_flash_error'$e->getMessage());
  334.         }
  335.         catch(Exception $e)
  336.         {
  337.             $this->addFlash('sonata_flash_error'$e->getMessage());
  338.         }
  339.         return $this->redirect($_SERVER['HTTP_REFERER']);
  340.     }
  341.     public function uploadContractAction(Request $request null) : Response
  342.     {
  343.         try
  344.         {
  345.             $existingObject $this->assertObjectExists($requesttrue);
  346.             if(!$existingObject) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  347.             if(!count($_FILES)) throw new InvalidArgumentException('ko.upload_contract.not_found_file');
  348.             $filePath = @$_FILES['UPLOAD_CONTRACT']['tmp_name'];//$this->kernel->getProjectDir().DIRECTORY_SEPARATOR."templates/report/$fileName";
  349.             $contractSigned = @$_FILES['UPLOAD_CONTRACT']['name'];
  350.             if(!$filePath) throw new InvalidArgumentException('ko.upload_contract.incorrect_file');
  351.             if(!$this->isValidFileContract(@$_FILES['UPLOAD_CONTRACT']['type'])) throw new InvalidArgumentException('ko.upload_contract.incorrect_file_type');
  352.             $contractSignedFile = new UploadedFile($filePath$contractSigned'application/pdf'nulltrue);
  353.             $existingObject->setContractSignedFile($contractSignedFile);
  354.             $this->om->persist($existingObject);
  355.             $this->om->flush();
  356.             $this->addFlash('sonata_flash_success'$this->trans('ok.upload_contract', [], 'flash'));
  357.         }
  358.         catch (NotFoundHttpException $e)
  359.         {
  360.             $this->addFlash('sonata_flash_error'$e->getMessage());
  361.         }
  362.         catch (InvalidArgumentException $e)
  363.         {
  364.             $this->addFlash('sonata_flash_error'$this->trans($e->getMessage(), [], 'flash'));
  365.         }
  366.         catch (Exception $e)
  367.         {
  368.             $this->addFlash('sonata_flash_error'$this->trans('ko.upload_contract', ['%error%' => $e->getMessage()], 'flash'));
  369.         }
  370.         catch (Throwable $e)
  371.         {
  372.             $this->addFlash('sonata_flash_error'$this->trans('ko.upload_contract', ['%error%' => $e->getMessage()], 'flash'));
  373.         }
  374.         finally
  375.         {
  376.             return $this->redirect($_SERVER['HTTP_REFERER']);
  377.         }
  378.     }
  379.     public function cardAction()
  380.     {
  381.     }
  382.     public function sendAction()
  383.     {
  384.     }
  385.     public function inProcessAction(Request $request)
  386.     {
  387.         try
  388.         {
  389.             $id $request->get($this->admin->getIdParameter());
  390.             $object $this->admin->getObject($id);
  391.             if (!$object) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  392.             $this->useCaseEnTramitacionOperacion->tramitacion($object);
  393.             $this->addFlash('sonata_flash_success'$this->trans('operacion.in_processed.ok', [], 'flash'));
  394.             return $this->redirect($this->generateUrl('admin_app_operacion_edit', ['id' => $object->getId()], UrlGenerator::ABSOLUTE_URL));
  395.         }
  396.         catch (NotFoundHttpException $e)
  397.         {
  398.             $this->addFlash('sonata_flash_error'$e->getMessage());
  399.         }
  400.         catch (EnTramitacionOperacionException $e)
  401.         {
  402.             $this->addFlash('sonata_flash_error'$this->trans($e->getMessage(), [], 'flash'));
  403.         }
  404.         return $this->redirect($_SERVER['HTTP_REFERER']);
  405.     }
  406.     public function processedAction(Request $request)
  407.     {
  408.         try
  409.         {
  410.             $id $request->get($this->admin->getIdParameter());
  411.             $object $this->admin->getObject($id);
  412.             if (!$object instanceof Operacion) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  413.             // 🔐 Control de autorización
  414. //            $this->denyAccessUnlessGranted(OperacionVoter::OPERACION_TRAMITAR, $object);
  415.             $this->useCaseTramitarOperacion->execute($object$request->query->has('deleteSold'));
  416.             $this->addFlash('sonata_flash_success'$this->trans('operacion.processed.ok', [], 'flash'));
  417.             return $this->redirectToRoute('admin_app_operacion_edit', ['id' => $object->getId()]);
  418.         }
  419.         catch (NotFoundHttpException TramitadaOperacionException $e)
  420.         {
  421.             $this->addFlash('sonata_flash_error'$this->trans($e->getMessage(), [], 'flash'));
  422.         }
  423.         return $this->redirect($_SERVER['HTTP_REFERER']);
  424.     }
  425.     public function confirmedAction(Request $request)
  426.     {
  427.         try
  428.         {
  429.             $id $request->get($this->admin->getIdParameter());
  430.             $object $this->admin->getObject($id);
  431.             if (!$object instanceof Operacion) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  432. //            // 🔒 Verificación de permisos (voter)
  433. //            $this->denyAccessUnlessGranted('OPERACION_CONFIRMAR', $object);
  434.             $this->useCaseConfirmarOperacion->execute($object);
  435.             $this->addFlash('sonata_flash_success'$this->trans('operacion.confirmed.ok', [], 'flash'));
  436.             return $this->redirectToRoute('admin_app_operacion_edit', ['id' => $object->getId()]);
  437.         }
  438.         catch (NotFoundHttpException ConfirmadaOperacionException $e)
  439.         {
  440.             $this->addFlash('sonata_flash_error'$this->trans($e->getMessage(), [], 'flash'));
  441.         }
  442.         return $this->redirect($_SERVER['HTTP_REFERER']);
  443.     }
  444.     // controlar que sea el admin
  445.     public function settleAction(Request $request)
  446.     {
  447.         try
  448.         {
  449.             $id $request->get($this->admin->getIdParameter());
  450.             $object $this->admin->getObject($id);
  451.             $dto SettleOperacionDTO::fromRequest($request);
  452.             if (!$object) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  453.             $this->useCaseAsentadaOperacion->execute($object$dto);
  454.             $this->addFlash('sonata_flash_success'$this->trans('operacion.settled.ok', [], 'flash'));
  455.             return $this->redirectToRoute('admin_app_operacion_edit', ['id' => $object->getId()]);
  456.         }
  457.         catch (NotFoundHttpException $e)
  458.         {
  459.             $this->addFlash('sonata_flash_error'$e->getMessage());
  460.         }
  461.         catch (AsentadaOperacionException $e)
  462.         {
  463.             $this->addFlash('sonata_flash_error'$this->trans($e->getMessage(), [], 'flash'));
  464.         }
  465.         return $this->redirect($_SERVER['HTTP_REFERER']);
  466.     }
  467.     public function finishAction(Request $request)
  468.     {
  469.         try
  470.         {
  471.             $id $request->get($this->admin->getIdParameter());
  472.             $object $this->admin->getObject($id);
  473.             $dto FinishOperacionDTO::fromRequest($request);
  474.             if (!$object) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  475.             $this->useCaseFinalizadaOperacion->finalizada($object$dto);
  476.             $this->addFlash('sonata_flash_success'$this->trans('operacion.finish.ok', [], 'flash'));
  477.             return $this->redirect($this->generateUrl('admin_app_operacion_edit', ['id' => $object->getId()], UrlGenerator::ABSOLUTE_URL));
  478.         }
  479.         catch (NotFoundHttpException $e)
  480.         {
  481.             $this->addFlash('sonata_flash_error'$e->getMessage());
  482.         }
  483.         catch (FinalizadaOperacionException $e)
  484.         {
  485.             $this->addFlash('sonata_flash_error'$this->trans($e->getMessage(), [], 'flash'));
  486.         }
  487.         return $this->redirect($_SERVER['HTTP_REFERER']);
  488.     }
  489.     public function cancelRelojAction(Request $request)
  490.     {
  491.         $error = [];
  492.         try {
  493.             $existingObject $this->assertObjectExists($requesttrue);
  494.             if(!$existingObject) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  495.             if(!$request->get("fechaCancelacion")) throw new InvalidArgumentException('ko.operacion.cancel_reloj.not_found_date_cancel');
  496.             $fechaCancelacion date_create_from_format('d-m-Y'$request->get("fechaCancelacion"));
  497.             $detalleCompraReloj $existingObject->getCompra()->getDetalle()->filter(fn($dv) => $dv->getReloj()?->getId() == $request->get('reloj'))->first();
  498.             $this->useCaseCancelarReloj->__invoke($detalleCompraReloj$fechaCancelacion);
  499.             if($this->isXmlHttpRequest($request))
  500.             {
  501.                 return $this->handleXmlHttpRequestSuccessResponse($request$existingObject);
  502.             }
  503.             $this->addFlash('sonata_flash_success'$this->trans('operacion.cancelar_reloj.ok', [ '%reloj%' => $detalleCompraReloj->getReloj() ], 'flash'));
  504.             return $this->redirect($this->generateUrl('admin_app_operacion_edit', ['id' => $existingObject->getId()], UrlGenerator::ABSOLUTE_URL));
  505.         }
  506.         catch (CanceladaOperacionException InvalidArgumentException NotFoundHttpException $e)
  507.         {
  508.             $errorTrans $this->trans($e->getMessage(), [], 'flash');
  509.             $this->addFlash('sonata_flash_error'$errorTrans);
  510.             $error = ['error' => $errorTrans];
  511.         }
  512.         if($this->isXmlHttpRequest($request))
  513.         {
  514.             return $this->json$errorResponse::HTTP_BAD_REQUEST);
  515.         }
  516.         return $this->redirect($_SERVER['HTTP_REFERER']);
  517.     }
  518.     // controlar que sea el admin
  519.     public function cancelAction(Request $request)
  520.     {
  521.         try
  522.         {
  523.             $id $request->get($this->admin->getIdParameter());
  524.             $object $this->admin->getObject($id);
  525.             $dto CancelOperacionDTO::fromRequest($request);
  526.             if (!$object) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  527.             $this->useCaseCanceladaOperacion->execute($object$dto);
  528.             $this->addFlash('sonata_flash_success'$this->trans('operacion.canceled.ok', [], 'flash'));
  529.             return $this->redirect($this->generateUrl('admin_app_operacion_edit', ['id' => $object->getId()], UrlGenerator::ABSOLUTE_URL));
  530.         }
  531.         catch (NotFoundHttpException $e)
  532.         {
  533.             $this->addFlash('sonata_flash_error'$e->getMessage());
  534.         }
  535.         catch (CanceladaOperacionException $e)
  536.         {
  537.             $this->addFlash('sonata_flash_error'$this->trans($e->getMessage(), [], 'flash'));
  538.         }
  539.         return $this->redirect($_SERVER['HTTP_REFERER']);
  540.     }
  541.     public function deleteAction(Request $request): Response
  542.     {
  543.         try
  544.         {
  545.             $id $request->get($this->admin->getIdParameter());
  546.             $object $this->admin->getObject($id);
  547.             if (!$object) throw new NotFoundHttpException('OPERACION_NOT_EXISTS');
  548.             $valoracion $object->getValoracion();
  549.             $this->useCaseBorradoOperacion->borrado($object);
  550.             $this->addFlash('sonata_flash_success'$this->trans('operacion.borrada.ok', [], 'flash'));
  551.             return $this->redirect($this->generateUrl('admin_app_valoracion_edit', ['id' => $valoracion->getId()], UrlGenerator::ABSOLUTE_URL));
  552.         }
  553.         catch (NotFoundHttpException $e)
  554.         {
  555.             $this->addFlash('sonata_flash_error'$e->getMessage());
  556.         }
  557.         catch (BorradoOperacionException $e)
  558.         {
  559.             $this->addFlash('sonata_flash_error'$this->trans($e->getMessage(), [], 'flash'));
  560.         }
  561.         return $this->redirect($_SERVER['HTTP_REFERER']);
  562.     }
  563.     public function switchOperacionAction()
  564.     {
  565.     }
  566.     public function controlUnconfirmedAction(Request $request)
  567.     {
  568.         $relojesVendidos = [];
  569.         $existingObject $this->assertObjectExists($requesttrue);
  570.         foreach ($existingObject->getVenta()->getDetalle() as $detalle)
  571.         {
  572.             if(($reloj $detalle->getReloj())->getPromociones()->getAcciones()->filter(fn($accion) => $accion instanceof AccionEstado && $accion->getEstado()->getKey() === EstadoRelojEnum::ESTADO_VENDIDO)->count())
  573.             {
  574.                 $relojesVendidos[] =  $reloj->getIDPerseo() . ' ' $reloj->getMarca() . ' ' $reloj->getModelo1();
  575.             }
  576.         }
  577.         return $this->renderJson([
  578.             'relojesVendidos' => count($relojesVendidos),
  579.             'relojes' => $relojesVendidos
  580.         ]);
  581.     }
  582.     private function normalizePath($path) {
  583.         $parts explode(DIRECTORY_SEPARATOR$path);
  584.         $absolutes = [];
  585.         foreach ($parts as $part) {
  586.             if ('.' == $part) {
  587.                 continue;
  588.             }
  589.             if ('..' == $part) {
  590.                 array_pop($absolutes);
  591.             } else {
  592.                 $absolutes[] = $part;
  593.             }
  594.         }
  595.         return implode(DIRECTORY_SEPARATOR$absolutes);
  596.     }
  597.     private function isValidFileContract(string $type) : bool
  598.     {
  599.         $valid false;
  600.         switch ($type)
  601.         {
  602.             case 'application/pdf':
  603.                 $valid true;
  604.                 break;
  605.             default:
  606.                 break;
  607.         }
  608.         return $valid;
  609.     }
  610. }