src/Controller/OrderController.php line 1346

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Company;
  4. use App\Entity\CompanyAddress;
  5. use App\Entity\Order;
  6. use App\Entity\OrderMessage;
  7. use App\Entity\Part;
  8. use App\Entity\Supplier;
  9. use App\Entity\User;
  10. use App\Entity\CompanySupplier;
  11. use App\Form\OrderFilesType;
  12. use App\Form\OrderPrototypeType;
  13. use App\Form\OrderSearchType;
  14. use App\Form\OrderType;
  15. use App\Form\OrderSupplierType;
  16. use App\Form\OrderBudgetType;
  17. use App\Repository\OrderRepository;
  18. use App\Security\Voter\OrderVoter;
  19. use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
  20. use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
  21. use Knp\Component\Pager\PaginatorInterface;
  22. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  23. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  24. use Symfony\Component\Form\FormInterface;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\HttpFoundation\JsonResponse;
  28. use Symfony\Component\Mailer\MailerInterface;
  29. use Symfony\Component\Mime\Address;
  30. use Symfony\Component\Routing\Annotation\Route;
  31. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  32. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  33. use Symfony\Component\HttpFoundation\StreamedResponse;
  34. use Symfony\Contracts\Translation\TranslatorInterface;
  35. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  36. use Knp\Snappy\Pdf;
  37. use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
  38. use App\Service\UtilService;
  39. use App\Service\OrderService;
  40. use App\Service\PartService;
  41. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  42. use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
  43. use Symfony\Component\Filesystem\Filesystem;
  44. use Symfony\Component\String\Slugger\AsciiSlugger;
  45. use Doctrine\Persistence\ManagerRegistry;
  46. use App\Service\EncryptDecryptService;
  47. /**
  48.  * @Route({"en": "/order",
  49.  *          "es": "/orden"})
  50.  */
  51. class OrderController extends AbstractController
  52. {
  53.     private $emailApp;
  54.     public const PAGE_ELEMENTS 25;
  55.     private $translator;
  56.     private $orderRepository;
  57.     private $util;
  58.     private $pdf;
  59.     private $orderService;
  60.     private $partService;
  61.     private $em;
  62.     private $partDir;
  63.     public function __construct(
  64.         string $emailApp,
  65.         TranslatorInterface $translator,
  66.         OrderRepository $orderRepository,
  67.         UtilService $utilService,
  68.         OrderService $orderService,
  69.         PartService $partService,
  70.         Pdf $knpSnappyPdf,
  71.         ManagerRegistry $doctrine,
  72.         string $partDir,
  73.         private EncryptDecryptService $encryptDecryptService)
  74.     {
  75.         $this->emailApp $emailApp;
  76.         $this->translator $translator;
  77.         $this->util $utilService;
  78.         $this->pdf $knpSnappyPdf;
  79.         $this->orderRepository $orderRepository;
  80.         $this->orderService $orderService;
  81.         $this->partService $partService;
  82.         $this->em $doctrine->getManager();
  83.         $this->partDir $partDir;
  84.     }
  85.     /**
  86.      * @Route({"en": "/list",
  87.      *         "es": "/listado"}, name="order_index", methods={"GET","POST"})
  88.      */
  89.     public function index(Request $requestOrderRepository $orderRepositoryPaginatorInterface $paginator): Response
  90.     {
  91.         $admin =$this->getUser();
  92.         $ms $this->util->getLicenseField($admin->getCompany(),'multi_select') && $admin->getRole()!='ROLE_CLIENT';
  93.         if($admin == NULL){
  94.             return $this->redirectToRoute('app_login');
  95.         }
  96.         $search = [];
  97.         $form $this->createForm(OrderSearchType::class, $search, ['user_admin' => $admin,'method' => 'GET']);
  98.         $form->handleRequest($request);
  99.         $orderBy null;
  100.         $filters = [
  101.             ['field'=>'company','title'=>'Empresa'],
  102.             ['field'=>'ref','title'=>'Referencia'],
  103.             ['field'=>'part','title'=>'Pieza'],
  104.             ['field'=>'supplier','title'=>'Centro de trabajo'],
  105.             ['field'=>'units','title'=>'Unidades'],
  106.             ['field'=>'updated_at','title'=>'Última modificación'],
  107.             ['field'=>'state','title'=>'Estado']
  108.         ];
  109.         if ($form->isSubmitted() && $form->isValid())
  110.         {
  111.             $orderBy $request->query->get('order_by');
  112.             $orders $orderRepository->findByName($form->getData(), $admin$orderBy);
  113.         } else {
  114.             $orders $orderRepository->buscarTodos($admin);
  115.         }
  116.         if($request->isMethod('POST')){
  117.             if($request->request->get('orders_delete')){
  118.                 $delIds $request->request->get('delIds',null);
  119.                 if($delIds){
  120.                     $orders explode(','$delIds);
  121.                     $successMsg '';
  122.                     $errorMsg '';
  123.                     foreach($orders as $orderId){
  124.                         $order $this->em->getRepository(Order::class)->find($orderId);
  125.                         if($order){
  126.                             $rmOrder $this->rmOrder($order);
  127.                             if($rmOrder['error']){
  128.                                 $errorMsg.= $this->translator->trans('Error orden {ref} : ',['{ref}'=>$order->getRef()]) . $rmOrder['msg'].'<br>';
  129.                             }
  130.                             else{
  131.                                 $successMsg.= $this->translator->trans('Orden {ref} eliminada correctamente',['{ref}'=>$order->getRef()]).'<br>';
  132.                             }
  133.                         }
  134.                     }
  135.                     if($successMsg){
  136.                         $this->addFlash('success'$successMsg);
  137.                     }
  138.                     if($errorMsg){
  139.                         $this->addFlash('danger'$successMsg);
  140.                     }
  141.                     return $this->redirectToRoute('order_index');
  142.                 }
  143.             }
  144.         }
  145.         // Creating pagnination
  146.         $pagination $paginator->paginate(
  147.             $orders,
  148.             $request->query->getInt('page'1),
  149.             self::PAGE_ELEMENTS
  150.         );
  151.         return $this->render('order/index.html.twig', [
  152.             'pagination' => $pagination,
  153.             'search_form' => $form->createView(),
  154.             'filters' => $filters,
  155.             'order_by' => $orderBy,
  156.             'ms' => $ms,
  157.             'user' => $this->getUser(),
  158.             'navbarTitle' => $this->translator->trans("Órdenes de trabajo")
  159.         ]);
  160.     }
  161.     /**
  162.      * @Route({"en": "/new/prototype",
  163.      *         "es": "/nuevo/prototipo"}, name="order_prototype_new", methods={"GET","POST"})
  164.      */
  165.     public function ºnewPrototype(Request $requestMailerInterface $mailerOrderRepository $orderRepository): Response
  166.     {
  167.         $em $this->em;
  168.         $admin $this->getUser();
  169.         $order = new Order();
  170.         $order->setUnits(1);
  171.         $order->setType(2);
  172.         $this->denyAccessUnlessGranted(OrderVoter::CREATE$order);
  173.         $fileMaxsizes $this->util->getCompanyFileMaxsizes($admin->getCompany());
  174.         $cs $em->getRepository(CompanySupplier::class)->findOneBy(['company'=>$this->getUser()->getCompany(),'supplier'=>$order->getSupplier()]);
  175.         $form $this->createForm(OrderPrototypeType::class, $order, ['user_admin' => $admin'part' => null'cs'=>$cs,'file_maxsizes' => $fileMaxsizes]);
  176.         $form->handleRequest($request);
  177.         if ($form->isSubmitted() && $form->isValid()) {
  178.             $createOrder $this->createOrder($order);
  179.             if($createOrder['error']) {
  180.                 $this->addFlash('danger''error: ' $createOrder['msg']);
  181.             }
  182.             $this->processOtherFiles($form$order5);
  183.             $em->persist($order);
  184.             $em->flush();
  185.             return $this->redirectToRoute('order_index');
  186.         }
  187.         return $this->render('order/new.html.twig', [
  188.             'order' => $order,
  189.             //'cs' => $cs,
  190.             'form' => $form->createView(),
  191.             'user' => $this->getUser(),
  192.             'navbarTitle' => $this->translator->trans("Solicitar presupuesto")
  193.         ]);
  194.     }
  195.     /**
  196.      * @Route({"en": "/new/{part}",
  197.      *         "es": "/nueva/{part}"}, name="order_new", methods={"GET","POST"})
  198.      */
  199.     public function new(Request $requestMailerInterface $mailerPart $partOrderRepository $orderRepository): Response
  200.     {
  201.         $em $this->em;
  202.         $admin $this->getUser();
  203.         $order = new Order();
  204.         $order->setType(1);
  205.         $this->denyAccessUnlessGranted(OrderVoter::CREATE$order);
  206.         $cs $em->getRepository(CompanySupplier::class)->findOneBy(['company'=>$part->getCompany(),'supplier'=>$part->getSupplier()]);
  207.         $form $this->createForm(OrderType::class, $order, ['user_admin' => $admin'part' => $part'cs'=>$cs]);
  208.         $form->handleRequest($request);
  209.         if ($form->isSubmitted() && $form->isValid()) {
  210.             $initMsg $this->translator->trans('Pieza') . ' ' $part->getRef() . ': ';
  211.             $createOrder $this->createOrder($order);
  212.             if($createOrder['error']){
  213.                 $this->addFlash('danger'$initMsg $createOrder['msg']);
  214.             }
  215.             else{
  216.                 $this->addFlash('success'$initMsg $this->translator->trans('Orden creada correctamente'));
  217.             }
  218.             return $this->redirectToRoute('order_index');
  219.         }
  220.         return $this->render('order/new.html.twig', [
  221.             'order' => $order,
  222.             'cs' => $cs,
  223.             'form' => $form->createView(),
  224.             'user' => $this->getUser(),
  225.             'navbarTitle' => $this->translator->trans("Solicitar presupuesto")
  226.         ]);
  227.     }
  228.     private function processOtherFiles(FormInterface $formOrder $order$limit=5){
  229.         $files $form->get('filesOrder')->getData();
  230.         if(count($files)>0){
  231.             $slugger = new AsciiSlugger();
  232.             $filenames = !empty($order->getFilesOrder()) ? explode(',',$order->getFilesOrder()) : [];
  233.             try {
  234.                 foreach($files as $file)
  235.                 {
  236.                     $originalFilename pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
  237.                     $safeFilename $slugger->slug($originalFilename);
  238.                     $newFilename $safeFilename.'-'.uniqid().'.'.$file->getClientOriginalExtension();
  239.                     if(!in_array($newFilename,$filenames)){
  240.                         if(count($filenames)>$limit){
  241.                             $this->addFlash('warning'$this->translator->trans('Se excedió el ḿaximo de archivos que se pueden cargar'));
  242.                             break;
  243.                         }
  244.                         else{
  245.                             $file->move($this->partDir$newFilename);
  246.                             $filenames[]=$newFilename;
  247.                             $order->setFilesOrder(implode(',',$filenames));
  248.                         }
  249.                     }
  250.                 }
  251.             }
  252.             catch (FileException $e) {
  253.                 $this->addFlash('danger'$this->translator->trans('Fallo en la carga de fichero'));
  254.             }
  255.         }
  256.     }
  257.     /**
  258.      * @Route({"en": "/new/bulk/{partIds}",
  259.      *         "es": "/nueva/masiva/{partIds}"}, name="order_bulk_new", methods={"GET","POST"})
  260.      */
  261.     public function newBulk(Request $requestOrderRepository $orderRepositorystring $partIds): Response
  262.     {
  263.         $user =$this->getUser();
  264.         $em $this->em;
  265.         $qb $em->createQueryBuilder();
  266.         if($user == NULL){
  267.             return $this->redirectToRoute('app_login');
  268.         }
  269.         $decodedPartIds explode(',',base64_decode($partIds));
  270.         $parts = [];
  271.         foreach($decodedPartIds as $partId){
  272.             $part $this->em->getRepository(Part::class)->find($partId);
  273.             if($part && $part->getSupplier() && $part->getCompany()==$user->getCompany() && !$part->getLocked()){
  274.                 $parts[] = $part;
  275.             }
  276.         }
  277.         if(empty($parts)){
  278.             $this->addFlash('danger'$this->translator->trans('Error inesperado'));
  279.             return $this->redirectToRoute('part_index');
  280.         }
  281.         if($request->isMethod('POST')){
  282.             $orders = (array) $request->request->get('orders');
  283.             if(!empty($orders) && count($orders)==4){
  284.                 $errorMsg = [];
  285.                 $successMsg = [];
  286.                 for($i=0;$i<count($orders['parts']);$i++){
  287.                     $partId $orders['parts'][$i];
  288.                     $part $em->getRepository(Part::class)->find($partId);
  289.                     if(!empty($part)){
  290.                         $shippingAddress null;
  291.                         if(!empty($orders['shipping_address'][$i])){
  292.                             $shippingAddress $em->getRepository(CompanyAddress::class)->find($orders['shipping_address'][$i]);
  293.                         }
  294.                         $order = new Order();
  295.                         $order->setPart($part);
  296.                         $order->setCompany($part->getCompany());
  297.                         $order->setSupplier($part->getSupplier());
  298.                         $order->setUser($user);
  299.                         $order->setShippingAddress($shippingAddress);
  300.                         $order->setUnits($orders['units'][$i]);
  301.                         $order->setObservations($orders['observations'][$i]);
  302.                         $initMsg $this->translator->trans('Pieza') . ' ' $part->getRef() . ': ';
  303.                         $createOrder $this->createOrder($order);
  304.                         if($createOrder['error']){
  305.                             $errorMsg[] = $initMsg $createOrder['msg'];
  306.                         }
  307.                         else{
  308.                             $successMsg[]=$initMsg $this->translator->trans('Orden creada correctamente');
  309.                         }
  310.                     }
  311.                     else{
  312.                         $errorMsg[] = $this->translator->trans('Pieza') . ' [' $partId ']: ' $this->translator->trans('Error inesperado');
  313.                     }
  314.                 }
  315.                 if($errorMsg){
  316.                     $this->addFlash('danger'implode('<br>',$errorMsg));
  317.                 }
  318.                 if($successMsg){
  319.                     $this->addFlash('success'implode('<br>',$successMsg));
  320.                 }
  321.                 return $this->redirectToRoute('order_index');
  322.             }
  323.             else{
  324.                 $this->addFlash('danger'$this->translator->trans('Error inesperado'));
  325.                 return $this->redirectToRoute('order_bulk_new',['partIds'=>$partIds]);
  326.             }
  327.         }
  328.         return $this->render('order/bulk_new.html.twig', [
  329.             'parts' => $parts,
  330.             'user' => $user,
  331.             'navbarTitle' => $this->translator->trans("Nuevas órdenes de trabajo")
  332.         ]);
  333.     }
  334.     private function createOrder(Order $order){
  335.         $em $this->em;
  336.         $orderRepository $this->orderRepository;
  337.         if($order->getPart()) {
  338.             $part $order->getPart();
  339.         }
  340.         $user $this->getUser();
  341.         $roleClient $user->getRole()=='ROLE_CLIENT';
  342.         $result = ['error'=>false,'msg'=>''];
  343.         if($order->getType() == 1) {
  344.             $company $part->getCompany();
  345.         } else {
  346.             $company $user->getCompany();
  347.         }
  348.         $lastRef $orderRepository->findLastRef($company);
  349.         if($order->getType() == 1) {
  350.             $supplierId $part->getSupplier();
  351.         } else {
  352.             $supplierId $order->getSupplier();
  353.         }
  354.         $cs $em->getRepository(CompanySupplier::class)->findOneBy(['company'=>$company,'supplier'=> $supplierId]);
  355.         $budgetRequired $cs $cs->getConfigStepBudget() : true;
  356.         $chiefConfirm $cs $cs->getConfigStepChiefConfirm() : true;
  357.         $order->setRef($lastRef);
  358.         $order->setChiefConfirm($chiefConfirm);
  359.         $order->setBudgetRequired($budgetRequired);
  360.         $order->setUnitsDecrypted($order->getUnits());
  361.         try
  362.         {
  363.             if(!$order->getId()){
  364.                 $em->persist($order);
  365.             }
  366.             //Bloqueo de pieza
  367.             if($order->getType() == 1) {
  368.                 $part $order->getPart();
  369.                 $part->setLocked(true);
  370.                 $part->setLockedAt(new \DateTime());
  371.                 $part->setLockedUser(null);
  372.             }
  373.             $em->flush();
  374.             $data['message']='Nueva orden creada';
  375.             $data['reference']=$order->getRef();
  376.             $data['path_name']='order_show';
  377.             $data['path_parameters']='id:'.$order->getId();
  378.             //Notificaciones - cliente
  379.             $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  380.             if(!$roleClient && $order->getCompany()!=$order->getSupplier()->getCompany()){
  381.                 //Notificaciones - proveedor
  382.                 $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  383.             }
  384.         } catch ( UniqueConstraintViolationException $e) {
  385.             $result['error']=true;
  386.             $result['msg'] = $this->translator->trans('Ya existe una orden de trabajo para esta pieza');
  387.         }
  388.         return $result;
  389.     }
  390.     /**
  391.      * @Route({"en": "/show/{id}",
  392.      *         "es": "/mostrar/{id}"}, name="order_show", methods={"GET","POST"})
  393.      */
  394.     public function show(Request $requestOrder $orderOrderRepository $orderRepository): Response
  395.     {
  396.         $this->denyAccessUnlessGranted(OrderVoter::VIEW$order);
  397.         $em $this->em;
  398.         $fs = new Filesystem();
  399.         $slugger = new AsciiSlugger();
  400.         $ds DIRECTORY_SEPARATOR;
  401.         $ordersDir $this->getParameter('kernel.project_dir').$ds.'public'.$ds.'orders';
  402.         $user $this->getUser();
  403.         $role $user->getRole();
  404.         if($order->getType() == 1){
  405.             $company $order->getPart()->getCompany();
  406.         } else {
  407.             $company $order->getCompany();
  408.         }
  409.         $fileMaxsizes $this->util->getCompanyFileMaxsizes($company);
  410.         //Formulario envío de presupuesto
  411.         $formBudget $this->createForm(OrderBudgetType::class, $order, ['user' => $user'file_maxsizes' => $fileMaxsizes]);
  412.         //Formulario envío de presupuesto
  413.         $formFiles $this->createForm(OrderFilesType::class, $order, [ 'file_maxsizes' => $fileMaxsizes]);
  414.         //Formulario observaciones y carga archivos proveedor
  415.         $form $this->createForm(OrderSupplierType::class, $order, ['user' => $user'part' => $order->getPart(), 'file_maxsizes' => $fileMaxsizes]);
  416.         if(!in_array($role,['ROLE_SUPPLIER_CHIEF','ROLE_SUPPLIER'])) {
  417.             $formFiles->handleRequest($request);
  418.             if ($formFiles->isSubmitted()) {
  419.                 if ($formFiles->isValid()) {
  420.                     $this->processOtherFiles($formFiles$order5);
  421.                     $em->persist($order);
  422.                     $em->flush();
  423.                 } else {
  424.                     $this->addFlash('danger'$this->translator->trans('Ha habido un error al procesar el formulario, revise los campos'));
  425.                 }
  426.             }
  427.         }
  428.         if(in_array($role,['ROLE_SUPPLIER_CHIEF','ROLE_SUPPLIER'])){
  429.             //Formulario envío de presupuesto
  430.             $formBudget->handleRequest($request);
  431.             if($formBudget->isSubmitted()){
  432.                 if($formBudget->isValid()){
  433.                     $files $request->files->get('order_budget')['files_budget'];
  434.                     $payTermsId $form->getData()->getPaymentTermsId();
  435.                     $filenames = !empty($order->getFilesBudget()) ? explode(',',$order->getFilesBudget()) : [];
  436.                     $filesLimit 5;
  437.                     if(count($files)>0){
  438.                         try {
  439.                             if(!$fs->exists($ordersDir)){
  440.                                 $fs->mkdir($ordersDir);
  441.                             }
  442.                             foreach($files as $file)
  443.                             {
  444.                                 $originalFilename pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
  445.                                 $safeFilename $slugger->slug($originalFilename);
  446.                                 $newFilename $safeFilename.'-budget-'.uniqid().'.'.$file->getClientOriginalExtension();
  447.                                 if(!in_array($newFilename,$filenames)){
  448.                                     $filenames[]=$newFilename;
  449.                                     if(count($filenames)>$filesLimit){
  450.                                         $this->addFlash('warning'$this->translator->trans('Se excedió el ḿaximo de archivos que se pueden cargar'));
  451.                                         break;
  452.                                     }
  453.                                     else{
  454.                                         $file->move($ordersDir$newFilename);
  455.                                         $order->setFilesBudget(implode(',',$filenames));
  456.                                     }
  457.                                 }
  458.                             }
  459.                         }
  460.                         catch (FileException $e) {
  461.                             $this->addFlash('danger'$this->translator->trans('Fallo en la carga de fichero'));
  462.                         }
  463.                         catch (IOExceptionInterface $e) {
  464.                             $this->addFlash('danger'$this->translator->trans('No se ha podido generar el directorio').' : '.$e->getPath());
  465.                         }
  466.                     }
  467.                     $order->setState(1);
  468.                     $order->setBudgetDate(new \DateTime());
  469.                     $order->markAsAproved();
  470.                     $order->setPaymentTerms($orderRepository->getPaymentTermsText($payTermsId));
  471.                     $em->persist($order);
  472.                     $em->flush();
  473.                     $this->addFlash('success'$this->translator->trans('Presupuesto enviado correctamente'));
  474.                     return $this->redirectToRoute('order_index');
  475.                 }
  476.                 else{
  477.                     $this->addFlash('danger'$this->translator->trans('Ha habido un error al procesar el formulario, revise los campos'));
  478.                 }
  479.             }
  480.             //Formulario observaciones y carga archivos proveedor
  481.             $form->handleRequest($request);
  482.             if($form->isSubmitted()){
  483.                 if($form->isValid()){
  484.                     $obs $request->get('order_supplier');
  485.                     $files $request->files->get('order_supplier')['files'];
  486.                     $filenames = !empty($order->getFilesSupplier()) ? explode(',',$order->getFilesSupplier()) : [];
  487.                     $filesLimit 5;
  488.                     if(count($files)>0){
  489.                         try {
  490.                             if(!$fs->exists($ordersDir)){
  491.                                 $fs->mkdir($ordersDir);
  492.                             }
  493.                             foreach($files as $file)
  494.                             {
  495.                                 $originalFilename pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
  496.                                 $safeFilename $slugger->slug($originalFilename);
  497.                                 $newFilename $safeFilename.'-report-'.uniqid().'.'.$file->getClientOriginalExtension();
  498.                                 if(!in_array($newFilename,$filenames)){
  499.                                     $filenames[]=$newFilename;
  500.                                     if(count($filenames)>$filesLimit){
  501.                                         $this->addFlash('warning'$this->translator->trans('Se excedió el ḿaximo de archivos que se pueden cargar'));
  502.                                         break;
  503.                                     }
  504.                                     else{
  505.                                         $file->move($ordersDir$newFilename);
  506.                                         $order->setFilesSupplier(implode(',',$filenames));
  507.                                     }
  508.                                 }
  509.                             }
  510.                         }
  511.                         catch (FileException $e) {
  512.                             $this->addFlash('danger'$this->translator->trans('Fallo en la carga de fichero'));
  513.                         }
  514.                         catch (IOExceptionInterface $e) {
  515.                             $this->addFlash('danger'$this->translator->trans('No se ha podido generar el directorio').' : '.$e->getPath());
  516.                         }
  517.                     }
  518.                     $em->persist($order);
  519.                     $em->flush();
  520.                     $this->addFlash('success'$this->translator->trans('Orden editada correctamente'));
  521.                     return $this->redirectToRoute('order_show',['id'=>$order->getId()]);
  522.                 }
  523.                 else{
  524.                     $this->addFlash('danger'$this->translator->trans('Ha habido un error al procesar el formulario, revise los campos'));
  525.                 }
  526.             }
  527.             if($request->query->has('rm')){
  528.                 $type $request->query->has('type') && $request->query->get('type')==2;
  529.                 $filenames =  explode(',',($type==$order->getFilesBudget() : $order->getFilesSupplier()));
  530.                 $index $request->query->get('rm');
  531.                 if(!empty($filenames[$index])){
  532.                     $fileToRemove $filenames[$index];
  533.                     if($fs->exists($ordersDir.$ds.$fileToRemove)){
  534.                         try {
  535.                             $fs->remove($ordersDir.$ds.$fileToRemove);
  536.                             unset($filenames[$index]);
  537.                             if($type==1){
  538.                                 $order->setFilesBudget(implode(',',$filenames));
  539.                             }
  540.                             else{
  541.                                 $order->setFilesSupplier(implode(',',$filenames));
  542.                             }
  543.                             $em->flush();
  544.                             $this->addFlash('success'$this->translator->trans('Archivo eliminado correctamente'));
  545.                         } catch (IOExceptionInterface $exception) {
  546.                             $this->addFlash('danger',$this->translator->trans('No se ha podido eliminar el archivo'));
  547.                         }
  548.                     }
  549.                 }
  550.                 return $this->redirectToRoute('order_show',['id'=>$order->getId()]);
  551.             }
  552.         }
  553.         if($request->query->get('download')){
  554.             $url $this->generateUrl('order_show',['id'=>$order->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
  555.             $qr $this->util->generateQrCode($url);
  556.             if($request->query->get('download')==1){
  557.                 $options = [
  558.                     'page-size' => 'A6',
  559.                     'orientation'=>'Landscape'
  560.                 ];
  561.                 $html =$this->renderView('order/pdf/tag.html.twig', [
  562.                     'order' => $order,
  563.                     'qr' => $qr,
  564.                     'user' => $user
  565.                 ]);
  566.                 return new PdfResponse(
  567.                     $this->pdf->getOutputFromHtml($html$options),
  568.                     $order->getRef().'_'.$this->translator->trans('etiqueta').'.pdf'
  569.                 );
  570.             }
  571.             else{
  572.                 $header $this->renderView'order/pdf/report_header.html.twig',[
  573.                     'order' => $order,
  574.                     'partByCat' => $this->partService->getPartByCat($order->getPart()),
  575.                     'qr' => $qr,
  576.                     'preview' => $order->getPart()->getFilePreview() ? $this->partDir DIRECTORY_SEPARATOR $order->getPart()->getFilePreview() : '',
  577.                     'user' => $user
  578.                 ] );
  579.                 $footer $this->renderView'order/pdf/report_footer.html.twig',[
  580.                     'order' => $order,
  581.                     'partByCat' => $this->partService->getPartByCat($order->getPart()),
  582.                     'qr' => $qr,
  583.                     'user' => $user
  584.                 ] );
  585.                 $options = [
  586.                     'header-html' => $header,
  587.                     'footer-html' => $footer,
  588.                     'page-size' => 'A4'
  589.                 ];
  590.                 $html =$this->renderView('order/pdf/report.html.twig', [
  591.                     'order' => $order,
  592.                     'sum' => $this->orderService->getOrderSummary($order),
  593.                     'partByCat' => $this->partService->getPartByCat($order->getPart()),
  594.                     'qr' => $qr,
  595.                     'user' => $user
  596.                 ]);
  597.                 return new PdfResponse(
  598.                     $this->pdf->getOutputFromHtml($html$options),
  599.                     $order->getRef().'_'.$this->translator->trans('hoja_produccion').'.pdf'
  600.                 );
  601.             }
  602.         }
  603.         if ($request->getMethod()=='POST') {
  604.             if ($this->isCsrfTokenValid('initiate'.$order->getId(), $request->request->get('_token'))) {
  605.                 $said $request->request->get('shipping_address');
  606.                 $type $request->request->get('request_order') ? 2;
  607.                 if($type==1){
  608.                     if($said>0){
  609.                         $shipping_address $em->getRepository(CompanyAddress::class)->find($said);
  610.                         $order->setShippingAddress($shipping_address);
  611.                     }
  612.                     $order->setState(0);
  613.                 }
  614.                 else{
  615.                     $order->setState(6);
  616.                     $order->setRejectUser($user);
  617.                     $order->setRejectDate(new \DateTime());
  618.                 }
  619.                 $order->markAsAproved(); //updated
  620.                 $em->flush();
  621.                 $data['message']='Orden de cliente solicitada';
  622.                 $data['reference']=$order->getRef();
  623.                 $data['path_name']='order_show';
  624.                 $data['path_parameters']='id:'.$order->getId();
  625.                 //Notificaciones - cliente
  626.                 $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  627.                 if($order->getCompany()!=$order->getSupplier()->getCompany()){
  628.                     //Notificaciones - proveedor
  629.                     $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  630.                 }
  631.                 $this->addFlash('success'$this->translator->trans('Orden de cliente solicitada'));
  632.                 return $this->redirectToRoute('order_index');
  633.             }
  634.         }
  635.         $addresses null;
  636.         if($order->getState()==and $order->getPart()){
  637.             $addresses $em->createQueryBuilder()
  638.                 ->select('ca')
  639.                 ->from(CompanyAddress::class,'ca')
  640.                 ->where("ca.company = {$order->getPart()->getSupplier()->getCompany()->getId()}")
  641.                 ->orderBy('ca.name''ASC')->getQuery()->getResult();
  642.         }
  643.         $prototypes null;
  644.         $canCreateProto =  true;
  645.         if($order->getType() == 2) {
  646.             $prototypes $em->getRepository(Part::class)->findBy(['prototypeOrder'=>$order->getId()]);
  647.             if($prototypes) {
  648.                 foreach ($prototypes as $prototype) {
  649.                     if($prototype->getPrototypeStatus() != Part::REFUSED ) {
  650.                         $canCreateProto false;
  651.                     }
  652.                 }
  653.             }
  654.         }
  655.         return $this->render('order/show.html.twig', [
  656.             'order' => $order,
  657.             'cs' => $em->getRepository(CompanySupplier::class)->findOneBy(['company'=>$company,'supplier'=>$order->getSupplier()]),
  658.             'user' => $user,
  659.             'fileMaxsizes' => $fileMaxsizes,
  660.             'form' => $form $form->createView() : null,
  661.             'formBudget' => $formBudget->createView(),
  662.             'formFiles' => $formFiles->createView(),
  663.             'addresses' => $addresses,
  664.             'navbarTitle' => $this->translator->trans("Orden de trabajo").' - '.$order->getRef(),
  665.             'prototypes' => $prototypes,
  666.             'canCreateProto' => $canCreateProto
  667.         ]);
  668.     }
  669.     /**
  670.      * @Route({"en": "/edit/{id}/{part}",
  671.      *         "es": "/editar/{id}/{part}"}, name="order_edit", methods={"GET","POST"})
  672.      */
  673.     public function edit(Request $requestOrder $orderPart $part): Response
  674.     {
  675.         $this->denyAccessUnlessGranted(OrderVoter::EDIT$order);
  676.         $admin $this->getUser();
  677.         $form $this->createForm(OrderType::class, $order, ['user_admin' => $admin'part' => $part]);
  678.         $form->handleRequest($request);
  679.         if ($form->isSubmitted() && $form->isValid()) {
  680.             $order->markAsAproved();
  681.             $this->em->flush();
  682.             $this->addFlash('success'$this->translator->trans('Orden editada correctamente'));
  683.             return $this->redirectToRoute('order_index');
  684.         }
  685.         return $this->render('order/edit.html.twig', [
  686.             'order' => $order,
  687.             'form' => $form->createView(),
  688.             'user' => $this->getUser(),
  689.             'navbarTitle' => $this->translator->trans("Editar orden").' - '.$order->getRef()
  690.         ]);
  691.     }
  692.     /**
  693.      * @Route({"en": "/accept/{id}",
  694.      *         "es": "/aceptar/{id}"}, name="order_accept", methods={"POST"})
  695.      */
  696.     public function accept(Request $requestMailerInterface $mailerOrder $orderOrderRepository $orderRepository): Response
  697.     {
  698.         $this->denyAccessUnlessGranted(OrderVoter::ACCEPT$order);
  699.         if ($this->isCsrfTokenValid('accept'.$order->getId(), $request->request->get('_token'))) {
  700.             $entityManager $this->em;
  701.             $user $this->getUser();
  702.             $role $user->getRole();
  703.             $currentState $order->getState();
  704.             if(!in_array($order->getState(),[1,2])){
  705.                 $this->addFlash('danger'$this->translator->trans('El presupuesto ya estaba aceptado'));
  706.                 return $this->redirectToRoute('order_index');
  707.             }
  708.             if($order->getState()==&& $order->getChiefConfirm() && $role=='ROLE_USER'){
  709.                 $this->addFlash('danger'$this->translator->trans('Requiere confirmación del usuario administrador'));
  710.                 return $this->redirectToRoute('order_index');
  711.             }
  712.             $state $order->getState() == 3;
  713.             // we dont want that a client use basket
  714.             if($role=='ROLE_CLIENT') {
  715.                 $state 3;
  716.             }
  717.             $acceptRef=null;
  718.             if($state==3){
  719.                 $acceptRef $orderRepository->getNewAcceptRef($order->getCompany());
  720.             }
  721.             $order->setState($state);
  722.             $order->setAcceptRef($acceptRef);
  723.             $order->markAsAproved();
  724.             $order->setApproveDate(new \DateTime());
  725.             if($role=='ROLE_USER'){
  726.                 $order->setApproveUserUser($user);
  727.                 $order->setApproveUserDate(new \DateTime());
  728.             }
  729.             else{
  730.                 $order->setApproveChiefUser($user);
  731.                 $order->setApproveChiefDate(new \DateTime());
  732.             }
  733.             $entityManager->persist($order);
  734.             $entityManager->flush();
  735.             if($state==&& $order->getType() == 1){
  736.                 try {
  737.                     //Si existen archivos encriptados se les asignan los grants correspondientes
  738.                     $this->encryptDecryptService->encryptPartGrants($order->getPart(), $order->getUnits());
  739.                 } catch (\Exception $e) {
  740.                     $this->addFlash('warning'$e->getMessage());
  741.                 }
  742.             }
  743.             $adminEmail $this->em->getRepository(User::class)->findOneBy(['role' => 'ROLE_ADMIN'])->getEmail();
  744.             $email = (new TemplatedEmail())
  745.             ->from(new Address($this->emailApp'Addvance3D'))
  746.             ->to($order->getUser()->getEmail())
  747.             ->bcc($adminEmail)
  748.             ->subject('Orden de trabajo aceptada')
  749.             ->htmlTemplate('order/email/acceptedEmail.html.twig')
  750.             ->context([
  751.                 'order' => $order,
  752.                 'user' => $user
  753.             ]);
  754.             $mailer->send($email);
  755.             $this->addFlash('success'$this->translator->trans('Presupuesto aceptado'));
  756.             $data['message']='Presupuesto aceptado';
  757.             $data['reference']=$order->getRef();
  758.             $data['path_name']='order_show';
  759.             $data['path_parameters']='id:'.$order->getId();
  760.             //Notificaciones - cliente
  761.             $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  762.             if($order->getCompany()!=$order->getSupplier()->getCompany() && $state==3){
  763.                 //Notificaciones - proveedor
  764.                 $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  765.             }
  766.         }
  767.         return $this->redirectToRoute('order_index');
  768.     }
  769.     /**
  770.      * @Route({"en": "/accept/supplier/{id}",
  771.      *         "es": "/aceptar/proveedor/{id}"}, name="order_accept_supplier", methods={"POST"})
  772.      */
  773.     public function acceptSupplier(Request $requestMailerInterface $mailerOrder $orderOrderRepository $orderRepository): Response
  774.     {
  775.         $this->denyAccessUnlessGranted(OrderVoter::ACCEPT_SUPPLIER$order);
  776.         if ($this->isCsrfTokenValid('accept'.$order->getId(), $request->request->get('_token'))) {
  777.             $entityManager $this->em;
  778.             $user $this->getUser();
  779.             $role $user->getRole();
  780.             $currentState $order->getState();
  781.             if ($currentState==0)
  782.             {
  783.                 $acceptRef $orderRepository->getNewAcceptRef($order->getCompany());
  784.                 $order->setState(3);
  785.                 $order->setAcceptRef($acceptRef);
  786.                 $order->markAsAproved();
  787.                 $order->setApproveSupplierUser($user);
  788.                 $order->setApproveSupplierDate(new \DateTime());
  789.                 $order->setApproveDate(new \DateTime());
  790.                 $entityManager->persist($order);
  791.                 $entityManager->flush();
  792.                 try {
  793.                     //Si existen archivos encriptados se les asignan los grants correspondientes para fabricacion
  794.                     if($order->getType() == 1) {
  795.                         $this->encryptDecryptService->encryptPartGrants($order->getPart(), $order->getUnits());
  796.                     }
  797.                 } catch (\Exception $e) {
  798.                     $this->addFlash('warning'$e->getMessage());
  799.                 }
  800.                 $adminEmail $this->em->getRepository(User::class)->findOneBy(['role' => 'ROLE_ADMIN'])->getEmail();
  801.                 $email = (new TemplatedEmail())
  802.                 ->from(new Address($this->emailApp'Addvance3D'))
  803.                 ->to($adminEmail)
  804.                 ->addTo($order->getUser()->getEmail())
  805.                 ->subject('Orden de trabajo aceptada')
  806.                 ->htmlTemplate('order/email/acceptedEmail.html.twig')
  807.                 ->context([
  808.                     'order' => $order,
  809.                     'user' => $user
  810.                 ]);
  811.                 $mailer->send($email);
  812.                 $this->addFlash('success'$this->translator->trans('Orden de trabajo aceptada'));
  813.                 $data['message']='Orden de trabajo aceptada';
  814.                 $data['reference']=$order->getRef();
  815.                 $data['path_name']='order_show';
  816.                 $data['path_parameters']='id:'.$order->getId();
  817.                 //Notificaciones - cliente
  818.                 $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  819.                 if($order->getCompany()!=$order->getSupplier()->getCompany()){
  820.                     //Notificaciones - proveedor
  821.                     $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  822.                 }
  823.             }else{
  824.                 $this->addFlash('danger'$this->translator->trans('La orden de trabajo ya estaba aceptada'));
  825.             }
  826.         }
  827.         return $this->redirectToRoute('order_index');
  828.     }
  829.     /**
  830.      * @Route({"en": "/reject/{id}",
  831.      *         "es": "/rechazar/{id}"}, name="order_reject", methods={"POST"})
  832.      */
  833.     public function reject(Request $requestMailerInterface $mailerOrder $order): Response
  834.     {
  835.         $this->denyAccessUnlessGranted(OrderVoter::REJECT$order);
  836.         if ($this->isCsrfTokenValid('reject'.$order->getId(), $request->request->get('_token'))) {
  837.             $entityManager $this->em;
  838.             $user $this->getUser();
  839.             $role $user->getRole();
  840.             $currentState $order->getState();
  841.             if ($currentState!=6)
  842.             {
  843.                 $order->setState(6);
  844.                 $order->markAsAproved();
  845.                 $order->setRejectUser($user);
  846.                 $order->setRejectDate(new \DateTime());
  847.                 $entityManager->persist($order);
  848.                 $entityManager->flush();
  849.                 $adminEmail $this->em->getRepository(User::class)->findOneBy(['role' => 'ROLE_ADMIN'])->getEmail();
  850.                 $email = (new TemplatedEmail())
  851.                 ->from(new Address($this->emailApp'Addvance3D'))
  852.                 ->to($adminEmail)
  853.                 ->addTo($order->getUser()->getEmail())
  854.                 ->subject('Orden de trabajo rechazada')
  855.                 ->htmlTemplate('order/email/rejectedEmail.html.twig')
  856.                 ->context([
  857.                     'order' => $order,
  858.                 ]);
  859.                 $mailer->send($email);
  860.                 $this->addFlash('success'$this->translator->trans('Presupuesto rechazado'));
  861.                 $data['message']='Presupuesto rechazado';
  862.                 $data['reference']=$order->getRef();
  863.                 $data['path_name']='order_show';
  864.                 $data['path_parameters']='id:'.$order->getId();
  865.                 //Notificaciones - cliente
  866.                 $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  867.                 if($order->getCompany()!=$order->getSupplier()->getCompany()){
  868.                     //Notificaciones - proveedor
  869.                     $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  870.                 }
  871.             }else{
  872.                 $this->addFlash('danger'$this->translator->trans('El presupuesto ya estaba rechazado'));
  873.             }
  874.         }
  875.         return $this->redirectToRoute('order_index');
  876.     }
  877.     /**
  878.      * @Route("/bulk/accept_reject", name="order_bulk_accept_reject", methods={"POST"})
  879.      */
  880.     public function bulk(Request $requestMailerInterface $mailerOrderRepository $orderRepository): Response
  881.     {
  882.         if ($this->isCsrfTokenValid('bulk_accept_reject'$request->request->get('_token'))) {
  883.             $em $this->em;
  884.             $user $this->getUser();
  885.             $role $user->getRole();
  886.             $state $request->request->get('type') == 6;
  887.             $orders explode(',',$request->request->get('orders'));
  888.             if ($this->isGranted('ROLE_USER') && !empty($state) && !empty($orders))
  889.             {
  890.                 $lastSupplierId=null;
  891.                 $acceptRef=null;
  892.                 $ordersRef=[];
  893.                 foreach($orders as $oid){
  894.                     $order $em->getRepository(Order::class)->find($oid);
  895.                     $order->setState($state);
  896.                     $order->markAsAproved();
  897.                     if($state==3){
  898.                         $order->setApproveDate(new \DateTime());
  899.                         if($role=='ROLE_USER'){
  900.                             $order->setApproveUserUser($user);
  901.                             $order->setApproveUserDate(new \DateTime());
  902.                         }
  903.                         else{
  904.                             $order->setApproveChiefUser($user);
  905.                             $order->setApproveChiefDate(new \DateTime());
  906.                         }
  907.                     }
  908.                     else{
  909.                         $order->setRejectUser($user);
  910.                         $order->setRejectDate(new \DateTime());
  911.                     }
  912.                     if($state==&& empty($acceptRef)){
  913.                         $acceptRef $orderRepository->getNewAcceptRef($order->getCompany());
  914.                     }
  915.                     $order->setAcceptRef($acceptRef);
  916.                     if(empty($lastSupplierId)){
  917.                         $lastSupplierId $order->getSupplier()->getId();
  918.                     }
  919.                     elseif($lastSupplierId != $order->getSupplier()->getId()){
  920.                         $lastSupplierId null;
  921.                         break;
  922.                     }
  923.                     $ordersRef[]=$order->getRef();
  924.                 }
  925.                 if(!empty($lastSupplierId)){
  926.                     $em->flush();
  927.                     if($state==3){
  928.                         foreach($orders as $oid){
  929.                             $order $em->getRepository(Order::class)->find($oid);
  930.                             try {
  931.                                 //Si existen archivos encriptados se les asignan los grants correspondientes
  932.                                 if($order->getType() == 1) {
  933.                                     $this->encryptDecryptService->encryptPartGrants($order->getPart(), $order->getUnits());
  934.                                 }
  935.                             } catch (\Exception $e) {
  936.                                 $this->addFlash('warning'$e->getMessage());
  937.                             }
  938.                         }
  939.                     }
  940.                     $subject $msgFlash $state=='Presupuestos aceptados' 'Presupuestos rechazados';
  941.                     $msgType $state=='aprobado' 'rechazado';
  942.                     $msg "El usuario {$user->getName()} {$user->getSurname()} ha $msgType los siguientes presupuestos : ";
  943.                     $msg.='<ul>';
  944.                     foreach($ordersRef as $ref){
  945.                         $msg.="<li>$ref</li>";
  946.                     }
  947.                     $msg.='</ul>';
  948.                     $adminEmail $this->em->getRepository(User::class)->findOneBy(['role' => 'ROLE_ADMIN'])->getEmail();
  949.                     $email = (new TemplatedEmail())
  950.                     ->from(new Address($this->emailApp'Addvance3D'))
  951.                     ->to($adminEmail)
  952.                     ->subject($this->translator->trans($subject))
  953.                     ->htmlTemplate('order/email/bulkAcceptedRejectedEmail.html.twig')
  954.                     ->context([
  955.                         'msg' => $msg,
  956.                         'user' => $user
  957.                     ]);
  958.                     $mailer->send($email);
  959.                     $this->addFlash('success'$this->translator->trans($msgFlash));
  960.                     $data['message']=$msgFlash;
  961.                     //Notificaciones - cliente
  962.                     $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  963.                     if($order->getCompany()!=$order->getSupplier()->getCompany()){
  964.                         //Notificaciones - proveedor
  965.                         $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  966.                     }
  967.                 }
  968.                 else{
  969.                     $this->addFlash('danger'$this->translator->trans('No se pueden aceptar/rechazar presupuestos de distintos centros de trabajo de forma masiva'));
  970.                 }
  971.             }else{
  972.                 $this->addFlash('danger'$this->translator->trans('Error inesperado'));
  973.             }
  974.         }
  975.         return $this->redirectToRoute('order_shopping');
  976.     }
  977.     /**
  978.      * @Route({"en": "/send/{id}",
  979.      *         "es": "/enviar/{id}"}, name="order_send", methods={"POST"})
  980.      */
  981.     public function send(Request $requestMailerInterface $mailerOrder $order): Response
  982.     {
  983.         $this->denyAccessUnlessGranted(OrderVoter::SEND$order);
  984.         if ($this->isCsrfTokenValid('send'.$order->getId(), $request->request->get('_token'))) {
  985.             $entityManager $this->em;
  986.             $user $this->getUser();
  987.             $role $user->getRole();
  988.             $currentState $order->getState();
  989.             if ($currentState!=4)
  990.             {
  991.                 $order->setState(4);
  992.                 $order->markAsAproved();
  993.                 $order->setSendUser($user);
  994.                 $order->setSendDate(new \DateTime());
  995.                 $entityManager->persist($order);
  996.                 $entityManager->flush();
  997.                 $this->addFlash('success'$this->translator->trans('Orden de trabajo enviada'));
  998.                 $data['message']='Orden de trabajo enviada';
  999.                 $data['reference']=$order->getRef();
  1000.                 $data['path_name']='order_show';
  1001.                 $data['path_parameters']='id:'.$order->getId();
  1002.                 //Notificaciones - cliente
  1003.                 $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  1004.                 if($order->getCompany()!=$order->getSupplier()->getCompany()){
  1005.                     //Notificaciones - proveedor
  1006.                     $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  1007.                 }
  1008.             }else{
  1009.                 $this->addFlash('danger'$this->translator->trans('La orden de trabajo ya estaba enviada'));
  1010.             }
  1011.         }
  1012.         return $this->redirectToRoute('order_index');
  1013.     }
  1014.     /**
  1015.      * @Route({"en": "/complete/{id}",
  1016.      *         "es": "/completar/{id}"}, name="order_complete", methods={"POST"})
  1017.      */
  1018.     public function complete(Request $requestMailerInterface $mailerOrder $order): Response
  1019.     {
  1020.         $this->denyAccessUnlessGranted(OrderVoter::COMPLETE$order);
  1021.         if ($this->isCsrfTokenValid('complete'.$order->getId(), $request->request->get('_token'))) {
  1022.             $em $this->em;
  1023.             $user $this->getUser();
  1024.             $cs $em->getRepository(CompanySupplier::class)->findOneBy(['company'=>$order->getCompany(),'supplier'=>$order->getSupplier()]);
  1025.             $configInDelivery $cs $cs->getConfigStepInDelivery() : true;
  1026.             if ($order->getState() == || ($order->getState()==&& !$configInDelivery))
  1027.             {
  1028.                 $order->setState(5);
  1029.                 $order->markAsCompleted();
  1030.                 $order->setCompleteUser($user);
  1031.                 $order->setCompleteDate(new \DateTime());
  1032.                 $em->persist($order);
  1033.                 $em->flush();
  1034.                 $adminEmail $this->em->getRepository(User::class)->findOneBy(['role' => 'ROLE_ADMIN'])->getEmail();
  1035.                 $email = (new TemplatedEmail())
  1036.                 ->from(new Address($this->emailApp'Addvance3D'))
  1037.                 ->to($adminEmail)
  1038.                 ->subject('Orden de trabajo completada')
  1039.                 ->htmlTemplate('order/email/completedEmail.html.twig')
  1040.                 ->context([
  1041.                     'order' => $order,
  1042.                 ]);
  1043.                 if($order->getType()== 2) {
  1044.                     $prototype $em->getRepository(Part::class)->findOneBy(array('prototypeOrder' => $order->getId(),'prototypeStatus' => Part::UNDER_VALIDATION));
  1045.                     $part = clone ($prototype);
  1046.                     $part->setType(1);
  1047.                     $part->setName($order->getPrototypeName());
  1048.                     $part->setSupplier(null);
  1049.                     $em->persist($part);
  1050.                     $prototype->setPrototypeStatus(Part::VALIDATED);
  1051.                     $em->persist($prototype);
  1052.                     $em->flush();
  1053.                 }
  1054.                 $mailer->send($email);
  1055.                 $this->addFlash('success'$this->translator->trans('Orden de trabajo completada'));
  1056.                 $data['message']='Orden de trabajo completada';
  1057.                 $data['reference']=$order->getRef();
  1058.                 $data['path_name']='order_show';
  1059.                 $data['path_parameters']='id:'.$order->getId();
  1060.                 //Notificaciones - cliente
  1061.                 $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  1062.                 if($order->getCompany()!=$order->getSupplier()->getCompany()){
  1063.                     //Notificaciones - proveedor
  1064.                     $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  1065.                 }
  1066.             }else{
  1067.                 $this->addFlash('danger'$this->translator->trans('La orden debe estar en entrega'));
  1068.             }
  1069.         }
  1070.         return $this->redirectToRoute('order_index');
  1071.     }
  1072.     /**
  1073.      * @Route({"en": "/delete/{id}",
  1074.      *         "es": "/borrar/{id}"}, name="order_delete", methods={"DELETE"})
  1075.      */
  1076.     public function delete(Request $requestOrder $order): Response
  1077.     {
  1078.         $this->denyAccessUnlessGranted(OrderVoter::DELETE$order);
  1079.         if ($this->isCsrfTokenValid('delete'.$order->getId(), $request->request->get('_token'))) {
  1080.             $rmOrder $this->rmOrder($order);
  1081.             if($rmOrder['error']){
  1082.                 $this->addFlash('danger'$rmOrder['msg']);
  1083.             }
  1084.             else{
  1085.                 $this->addFlash('success'$this->translator->trans('Orden eliminada correctamente'));
  1086.             }
  1087.         }
  1088.         return $this->redirectToRoute('order_index');
  1089.     }
  1090.     private function rmOrder(Order $order){
  1091.         $em $this->em;
  1092.         $result = ['error'=>false,'msg'=>''];
  1093.         try {
  1094.             $em->remove($order);
  1095.             $em->flush();
  1096.         } catch (ForeignKeyConstraintViolationException $e) {
  1097.             $result = ['error'=>true'msg'=>$this->translator->trans('No se puede eliminar una orden asociada')];
  1098.         }
  1099.         return $result;
  1100.     }
  1101.     /**
  1102.      * @Route({"en": "/shopping",
  1103.      *         "es": "/cesta"}, name="order_shopping", methods={"GET"})
  1104.      */
  1105.     public function shopping(Request $requestOrderRepository $orderRepository): Response
  1106.     {
  1107.         $admin =$this->getUser();
  1108.         if($admin == NULL){
  1109.             return $this->redirectToRoute('app_login');
  1110.         }
  1111.         $orders $orderRepository->getShoppingCar($admin);
  1112.         return $this->render('order/shopping.html.twig', [
  1113.             'orders' => $orders,
  1114.             'navbarTitle' => $this->translator->trans("Cesta")
  1115.         ]);
  1116.     }
  1117.     /**
  1118.      * @Route("/chat/message", name="order_chat_message", methods={"POST"})
  1119.      */
  1120.     public function chatMessage(Request $requestMailerInterface $mailerOrderRepository $orderRepository): JsonResponse
  1121.     {
  1122.         $result = ['error'=>false,'msg'=>'','data'=>[]];
  1123.         $em $this->em;
  1124.         $user $this->getUser();
  1125.         $type $request->request->get('type',1); //1:Read, 2:Send/read
  1126.         $message $request->request->get('message');
  1127.         $oid $request->request->get('oid');
  1128.         if (empty($oid) || empty($user))
  1129.         {
  1130.             $result = ['error'=>true,'msg'=>$this->translator->trans("Error inesperado")];
  1131.         }
  1132.         elseif($type==&& empty($message)){
  1133.             $result = ['error'=>true,'msg'=>$this->translator->trans("El mensaje no puede estar vacío")];
  1134.         }
  1135.         else{
  1136.             $order $em->getRepository(Order::class)->find($oid);
  1137.             if(empty($order)){
  1138.                 $result = ['error'=>true,'msg'=>$this->translator->trans("Error inesperado")];
  1139.             }
  1140.             else{
  1141.                 if($type==2){
  1142.                     $om = new OrderMessage();
  1143.                     $om->setOrder($order);
  1144.                     $om->setUser($user);
  1145.                     $om->setDateAdded(new \DateTime());
  1146.                     $om->setMessage($message);
  1147.                     $em->persist($om);
  1148.                     $em->flush();
  1149.                     $messages $em->getRepository(OrderMessage::class)->findBy(['order_'=>$order,'user'=>$user],['date_added'=>'DESC'],2);
  1150.                     if(count($messages)<|| ($messages[0]->getDateAdded()->format('U') - $messages[1]->getDateAdded()->format('U') > 300)){
  1151.                         $data['message']='Nuevo mensaje de chat';
  1152.                         $data['reference']=$order->getRef();
  1153.                         $data['path_name']='order_show';
  1154.                         $data['path_parameters']='id:'.$order->getId();
  1155.                         if($user->getCompany()->getType()==2){
  1156.                             //Msg generado por proveedor, Notificaciones - cliente
  1157.                             $this->util->notifications($order->getCompany(), 3$data$this->getUser(), $order->getId());
  1158.                         }
  1159.                         else{
  1160.                             //Msg generado por proveedor, Notificaciones - proveedor
  1161.                             $this->util->notifications($order->getSupplier()->getCompany(), 3$data$this->getUser(), $order->getId());
  1162.                         }
  1163.                     }
  1164.                 }
  1165.                 $messages $qb $em->createQueryBuilder()
  1166.                                 ->select('o,u,om')
  1167.                                 ->from(OrderMessage::class,'om')
  1168.                                 ->join('om.order_','o')
  1169.                                 ->join('om.user','u')
  1170.                                 ->where('om.order_ = :order')
  1171.                                 ->orderBy('om.date_added','ASC')
  1172.                                 ->setParameters(['order'=>$order])
  1173.                                 ->getQuery()->getArrayResult();
  1174.                 $result['data']=$messages;
  1175.             }
  1176.         }
  1177.         return new JsonResponse($result);
  1178.     }
  1179.     /**
  1180.      * @Route({"en": "/export/{id}",
  1181.      *         "es": "/exportar/{id}"}, defaults={"id" = null}, name="order_export", methods={"GET"})
  1182.      */
  1183.     public function export(OrderRepository $orderRepositoryOrder $order null)
  1184.     {
  1185.         $trans $this->translator;
  1186.         if (null !== $order)
  1187.         {
  1188.             $filename $trans->trans("AD2_orden_"). $order->getRef() . '_' time() . ".xlsx";
  1189.         }else
  1190.         {
  1191.             $filename $trans->trans("AD2_ordenes_"). time() . ".xlsx";
  1192.         }
  1193.         $admin =$this->getUser();
  1194.         $company $admin->getCompany();
  1195.         $colorARGB $company && $company->getCorporateColor() ? str_replace('#','',$company->getCorporateColor()) : 'DD9933';
  1196.         $spreadsheet = new Spreadsheet();
  1197.         $sheet $spreadsheet->getActiveSheet();
  1198.         //$sheet->setTitle('Addvance Users');
  1199.         $sheet->getCell('A1')->setValue($trans->trans('Referencia orden'));
  1200.         $sheet->getCell('B1')->setValue($trans->trans('Empresa'));
  1201.         $sheet->getCell('C1')->setValue($trans->trans('Pieza'));
  1202.         $sheet->getCell('D1')->setValue($trans->trans('Referencia pieza'));
  1203.         $sheet->getCell('E1')->setValue($trans->trans('Centro de trabajo'));
  1204.         $sheet->getCell('F1')->setValue($trans->trans('Unidades'));
  1205.         $sheet->getCell('G1')->setValue($trans->trans('Estado'));
  1206.         $sheet->getCell('H1')->setValue($trans->trans('Pedido'));
  1207.         $sheet->getCell('I1')->setValue($trans->trans('Autor'));
  1208.         $sheet->getCell('J1')->setValue($trans->trans('Fecha de creación'));
  1209.         $sheet->getCell('K1')->setValue($trans->trans('Fecha Revisión'));
  1210.         $sheet->getCell('L1')->setValue($trans->trans('Fecha de finalización'));
  1211.         $sheet->getCell('M1')->setValue($trans->trans('Observaciones'));
  1212.         $styleArrayFirstRow = [
  1213.             'font' => [
  1214.                 'bold' => true,
  1215.                 'color' => array('rgb' => 'FFFFFF'),
  1216.             ]
  1217.         ];
  1218.         $highestColumn $sheet->getHighestColumn();
  1219.         $sheet->getStyle('A1:M1')->applyFromArray($styleArrayFirstRow);
  1220.         //$sheet->getStyle('A')->applyFromArray($styleArrayFirstRow);
  1221.         //$sheet->getColumnDimension('A')->setWidth(30);
  1222.         //$sheet->getStyle('A')->getFont()->setBold(true);
  1223.         $sheet->getDefaultColumnDimension()->setWidth(30);
  1224.         $sheet
  1225.             ->getStyle('A1:M1')
  1226.             ->getFill()
  1227.             ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
  1228.             ->getStartColor()
  1229.             ->setARGB($colorARGB);
  1230.         if (null!== $order)
  1231.         {
  1232.             $sheet->fromArray($orderRepository->generateExport($admin$order),null'A2'true);
  1233.         }else
  1234.         {
  1235.             $sheet->fromArray($orderRepository->generateExport($admin),null'A2'true);
  1236.         }
  1237.         $writer = new Xlsx($spreadsheet);
  1238.         $response =  new StreamedResponse(
  1239.             function () use ($writer) {
  1240.                 $writer->save('php://output');
  1241.             }
  1242.         );
  1243.         $response->headers->set('Content-Type''application/vnd.ms-excel');
  1244.         $response->headers->set('Content-Disposition''attachment;filename="'.$filename.'"');
  1245.         $response->headers->set('Cache-Control','max-age=0');
  1246.         return $response;
  1247.     }
  1248. }