src/Controller/ProductController.php line 48

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\IncomingOrder;
  4. use App\Entity\Product;
  5. use App\Entity\ProductIn;
  6. use App\Form\ProductTestType;
  7. use App\Form\ProductType;
  8. use App\Form\ProductTypeFieldsType;
  9. use App\Form\SearchProductByProductTypeType;
  10. use App\Repository\IncomingOrderRepository;
  11. use App\Repository\ProductFieldRepository;
  12. use App\Repository\ProductRepository;
  13. use App\Repository\ProductTypeRepository;
  14. use App\Service\FileUploader;
  15. use App\Service\ProductImportService;
  16. use Doctrine\DBAL\Exception;
  17. use Doctrine\ORM\EntityManagerInterface;
  18. use Knp\Component\Pager\PaginatorInterface;
  19. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  20. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  21. use Symfony\Component\HttpFoundation\JsonResponse;
  22. use Symfony\Component\HttpFoundation\Request;
  23. use Symfony\Component\HttpFoundation\Response;
  24. use Symfony\Component\Process\Process;
  25. use Symfony\Component\Routing\Annotation\Route;
  26. use App\Form\ProductImportType;
  27. use Symfony\Component\Validator\ConstraintViolationInterface;
  28. /**
  29.  * @Route("/admin/product")
  30.  */
  31. class ProductController extends AbstractController
  32. {
  33.     private string $importTargetDirectory;
  34.     private string $projectDir;
  35.     public function __construct($importTargetDirectory$projectDir)
  36.     {
  37.         $this->projectDir $projectDir;
  38.         $this->importTargetDirectory $importTargetDirectory;
  39.     }
  40.     /**
  41.      * @Route("/", name="product_index", methods={"GET"})
  42.      */
  43.     public function index(ProductRepository $productRepository,
  44.                           ProductTypeRepository $productTypeRepository,
  45.                           PaginatorInterface $paginatorRequest $request,
  46.                           EntityManagerInterface $em): Response
  47.     {
  48.         $queryString $request->query->get('query');
  49.         $advancedSearch $request->query->get('advancedSearch');
  50.         if ($queryString){
  51.             $query $productRepository->findBySearchQuery (['query' => $queryString]);
  52.         }else{
  53.             $queryParams $this->get_params_from_search_query($request);
  54.             $query $productRepository->findBySearchQuery($queryParams);
  55.         }
  56.         //$product = $query->getResult();
  57.         //$products = $productRepository->findAll();
  58.         $pagination $paginator->paginate(
  59.             $query/* query NOT result */
  60.             $request->query->getInt('page'1), /*page number*/
  61.             20/*limit per page*/
  62.             [
  63.                 'defaultSortFieldName'      => 'p.createdAt',
  64.                 'defaultSortDirection' => 'desc'
  65.             ]
  66.         );
  67.         $renderedForm '';
  68.         $productType null;
  69.         if (!empty($queryParams['product_type_id'])){
  70.             $options['submitted_data'] = $queryParams;
  71.             $form $this->createForm(SearchProductByProductTypeType::class,
  72.                 null,
  73.                 $options);
  74.             $renderedForm $this->renderView('product/search_by_product_type.html.twig', [
  75.                 'form' => $form->createView(),
  76.             ]);
  77.             $productType $productTypeRepository->find($queryParams['product_type_id']);
  78.         }
  79.         return $this->render('product/index.html.twig', [
  80.             'pagination' => $pagination,
  81.             'productType' => $productType,
  82.             'search_by_type_form' => $renderedForm,
  83.             'advancedSearch' => $advancedSearch,
  84.         ]);
  85.     }
  86.     /**
  87.      * @Route("/new", name="product_new", methods={"GET","POST"})
  88.      */
  89.     public function new(Request $request): Response
  90.     {
  91.         $product = new Product();
  92.         $productTypeId $request->request->get('product_type');
  93.         $fieldsOnly $request->request->get('fields_only');
  94.         if (isset($fieldsOnly) &&
  95.             $fieldsOnly === 'true'){
  96.             $form $this->createForm(ProductType::class, $product, ['is_fields_only' => true]);
  97.             $form->submit(['product_type' => $request->request->get('product_type')], false);
  98.         }else{
  99.             $form $this->createForm(ProductType::class, $product);
  100.             $form->handleRequest($request);
  101.         }
  102.         //$form = $this->createForm(ProductType::class, $product, ['new_product' => true]);
  103.         //$form->handleRequest($request);
  104.         $globalErrors $form->getErrors();
  105.         if ($form->isSubmitted() && $form->isValid()) {
  106.             $entityManager $this->getDoctrine()->getManager();
  107.             $entityManager->persist($product);
  108.             $entityManager->flush();
  109.             return $this->redirectToRoute('product_index');
  110.         }
  111.         return $this->render('product/new.html.twig', [
  112.             'product' => $product,
  113.             'form' => $form->createView(),
  114.             'new' => true,
  115.             /*'isFieldsOnly' => true*/
  116.         ]);
  117.     }
  118.     /**
  119.      * @Route ("/import", name="product_import", methods={"GET", "POST"})
  120.      */
  121.     public function import(Request $requestFileUploader $fileUploader,
  122.                            ProductImportService $productImportServiceProductTypeRepository $productTypeRepository): Response
  123.     {
  124.         $uploadedFile $request->files->get('file');
  125.         if ($uploadedFile){
  126.             $msg '';
  127.             //$mimeType = $uploadedFile->getMi
  128.             $uploadedFileName $fileUploader->upload($uploadedFile);
  129.             if (is_string($uploadedFileName)){
  130.                 return $this->json([
  131.                     'result' => 'success',
  132.                     'fileName' => $uploadedFileName
  133.                 ], 201);
  134.             }else{
  135.                 if (!== count($uploadedFileName)) {
  136.                     // there are errors, now you can show them
  137.                     /* @var $violation  ConstraintViolationInterface  */
  138.                     foreach ($uploadedFileName as $violation) {
  139.                         //$test = 'getMessage';
  140.                         //$msg .= $violation->$test().'<br>';
  141.                         $msg .= $violation->getMessage();
  142.                     }
  143.                 }
  144.             }
  145.             return $this->json([
  146.                 'result' => 'failure',
  147.                 'msg' => $msg
  148.             ], 400);
  149.         }
  150.         $productTypes $productTypeRepository->findAll();
  151.         //$form = $this->createForm(ProductImportType::class);
  152.         return $this->render('product/import.html.twig', [
  153.             'importTargetDirectory' => $this->importTargetDirectory,
  154.             //'form' => $form->createView(),
  155.             'productTypes' => $productTypes
  156.         ]);
  157.     }
  158.     /**
  159.      * @Route("/start_import", name="start_import", options={"expose"=true})
  160.      */
  161.     public function start_import(Request $requestProductImportService $productImportService): Response
  162.     {
  163.         // $fileName = 'beautifulthingsdaybookascolourstock-60ee4ac176486.csv';
  164.         $fileName $request->request->get("fileName");
  165.         $productTypeId $request->request->get("productType");
  166.         $user $this->getUser();
  167.         $productImportServiceEntry $productImportService->createImportEntry($fileName$user);
  168.         $entryId $productImportServiceEntry->getId();
  169.         $process Process::fromShellCommandline('/usr/bin/php7.4 '.$this->projectDir.'/bin/console app:product-import '.$entryId.' '.$productTypeId' &');
  170.         $process->start();
  171.         /*        exec('/usr/bin/php7.4 /home/www/stage-inventory.voom.co.nz/releases/4/bin/console app:product-import '.$entryId.
  172.                     ' >> '.$this->importTargetDirectory.'/temp.log &');*/
  173.         sleep(1);
  174.         return $this->json([
  175.                 'csv_file_name' => $fileName,
  176.                 'statusFileName' => $entryId.'_import_status.json'
  177.             ]);
  178.     }
  179.     /**
  180.      * @Route("/get_product_types", name="get_product_types", methods={"GET"}, options={"expose"=true})
  181.      */
  182.     public function getProductTypes(ProductTypeRepository $productTypeRepository):Response
  183.     {
  184.         $results = [];
  185.         $types $productTypeRepository->findAll();
  186.         foreach ($types as $type){
  187.             /* @var \App\Entity\ProductType $type */
  188.             $results['results'][] = [
  189.                 'id' => htmlspecialchars($type->getId(), \ENT_COMPAT | \ENT_HTML5),
  190.                 'text' => htmlspecialchars($type->getName(),\ENT_COMPAT | \ENT_HTML5)
  191.             ];
  192.         }
  193.         return $this->json($results);
  194.     }
  195.     /**
  196.      * @Route("/search_by_product_type", methods={"GET"}, name="search_by_product_type", options={"expose"=true})
  197.      *
  198.      */
  199.     function search_by_product_type(Request $requestProductTypeRepository $productTypeRepository
  200.     ):Response
  201.     {
  202.         $productType $productTypeRepository->find($request->get('product_type_id'));
  203.         if ($productType){
  204.             $form $this->createForm(SearchProductByProductTypeType::class,
  205.                 null,
  206.                 ['submitted_data' => [
  207.                     'product_type_id' => $productType->getId()
  208.                 ]]
  209.             );
  210.             return $this->render('product/search_by_product_type.html.twig', [
  211.                 'form' => $form->createView(),
  212.             ]);
  213.         }
  214.         return new Response('Product Type NOT found.');
  215.     }
  216.     /**
  217.      * @Route("/{id}", name="product_show", methods={"GET"}, requirements={"id":"\d+"})
  218.      */
  219.     public function show(Product $product): Response
  220.     {
  221.         return $this->render('product/show.html.twig', [
  222.             'product' => $product,
  223.         ]);
  224.     }
  225.     /**
  226.      * @Route("/get_product_type_fields/new/{product_type_id}", name="new_get_product_type_fields",
  227.      *     methods={"GET", "POST"}, options={"expose"=true})
  228.      * @ParamConverter("productType", options={"id" = "product_type_id"})
  229.      */
  230.     public function new_get_product_type_fields(Request $request, \App\Entity\ProductType $productType,
  231.                                             EntityManagerInterface $entityManager,
  232.                                             ProductRepository $productRepository): Response
  233.     {
  234.         $product = new Product();
  235.         $form $this->createForm(ProductTypeFieldsType::class, $product, [
  236.             'new_product' => true,
  237.             'product_type' => $productType
  238.         ]);
  239.         //Pre populate data
  240.         //$form->get('size')->setData('Test');
  241.         $form->handleRequest($request);
  242.         return $this->render('product/product_type_fields_form.twig', [
  243.             'product' => $product,
  244.             'form' => $form->createView(),
  245.             //'productInOuts' => $productRepository->productInAndOut($product)
  246.         ]);
  247.     }
  248.     /**
  249.      * @Route("/get_product_type_fields/{id}", name="get_product_type_fields", methods={"GET", "POST"}
  250.      *     , options={"expose"=true})
  251.      */
  252.     public function get_product_type_fields(Request $requestProduct $product,
  253.                                             EntityManagerInterface $entityManager,
  254.                          ProductRepository $productRepository): Response
  255.     {
  256.         $form $this->createForm(ProductTypeFieldsType::class, $product);
  257.         //Pre populate data
  258.         //$form->get('size')->setData('Test');
  259.         $form->handleRequest($request);
  260.         return $this->render('product/product_type_fields_form.twig', [
  261.             'product' => $product,
  262.             'form' => $form->createView(),
  263.             //'productInOuts' => $productRepository->productInAndOut($product)
  264.         ]);
  265.     }
  266.     /**
  267.      * @Route("/{id}/edit", name="product_edit", methods={"GET","POST"}, requirements={"id":"\d+"}, options={"expose"=true})
  268.      * @throws Exception
  269.      */
  270.     public function edit(Request $requestProduct $productEntityManagerInterface $entityManager,
  271.                          ProductRepository $productRepository): Response
  272.     {
  273.         //just return the form
  274.         $fieldsOnly $request->request->get('fields_only');
  275.         if (isset($fieldsOnly) &&
  276.             $fieldsOnly === 'true'){
  277.             $form $this->createForm(ProductType::class, $product, ['is_fields_only' => true]);
  278.             $form->submit(['product_type' => $request->request->get('product_type')], false);
  279.         }else{
  280.             $form $this->createForm(ProductType::class, $product);
  281.             $form->handleRequest($request);
  282.         }
  283.         if ($this->isCsrfTokenValid('delete'.$product->getId(), $request->request->get('_token'))) {
  284.             $entityManager $this->getDoctrine()->getManager();
  285.             $entityManager->remove($product);
  286.             $entityManager->flush();
  287.             $this->addFlash('success''Product deleted.');
  288.             $this->redirectToRoute('product_index');
  289.         }
  290.         if ($form->isSubmitted() && $form->isValid()) {
  291.           /*  $customFields = $product->getProductType()->getProductTypeFields()->getValues();
  292.             foreach ($customFields as $field){
  293.                 //$productField = $productFieldRepository->find();
  294.             }*/
  295.             //dd($product);
  296.             $entityManager->flush();
  297.             $this->addFlash('success''Product updated.');
  298.             return $this->redirectToRoute('product_index');
  299.         }
  300.         return $this->render('product/edit.html.twig', [
  301.             'product' => $product,
  302.             'form' => $form->createView(),
  303.             'productInOuts' => $productRepository->productInAndOut($product)
  304.         ]);
  305.     }
  306.     /**
  307.      * @Route("/{id}", name="product_delete", methods={"POST"}, requirements={"id":"\d+"})
  308.      */
  309.     public function delete(Request $requestProduct $product): Response
  310.     {
  311.         if ($this->isCsrfTokenValid('delete'.$product->getId(), $request->request->get('_token'))) {
  312.             $entityManager $this->getDoctrine()->getManager();
  313.             $entityManager->remove($product);
  314.             $entityManager->flush();
  315.         }
  316.         return $this->redirectToRoute('product_index');
  317.     }
  318.     /**
  319.      * @Route("/api/get_stock/{code}")
  320.      */
  321.     public function getStock(): Response
  322.     {
  323.         return $this->json(['test']);
  324.     }
  325.     /**
  326.      * @Route ("/{id}/update_hold_qty", name="product_update_hold_qty",
  327.      *     methods={"POST"}, requirements={"id":"\d+"})
  328.      */
  329.     public function updateHoldQty(Request $requestProduct $productEntityManagerInterface $entityManager): Response
  330.     {
  331.         $updateHoldQty $request->request->get('qty');
  332.         $product->setHold($updateHoldQty);
  333.         $entityManager->flush();
  334.         return $this->json(['result' => 'success']);
  335.     }
  336.     /**
  337.      * @Route ("/{id}/update_qty", name="product_update_qty",
  338.      *     methods={"POST"}, requirements={"id":"\d+"})
  339.      */
  340.     public function updateQty(Request $requestProduct $productEntityManagerInterface $entityManager): Response
  341.     {
  342.         $updateHoldQty $request->request->get('qty');
  343.         $product->setQty($updateHoldQty);
  344.         $entityManager->flush();
  345.         return $this->json(['result' => 'success']);
  346.     }
  347.     /**
  348.      * @Route("/{id}/edit_test", name="product_edit_test", methods={"GET","POST"}, requirements={"id":"\d+"})
  349.      */
  350.     public function editTest(Request $requestProduct $productEntityManagerInterface $entityManager,
  351.                          ProductFieldRepository $productFieldRepository): Response
  352.     {
  353.         $fields $product->getProductType()->getProductTypeFields();
  354.         $form $this->createForm(ProductTestType::class, $product);
  355.         $form->handleRequest($request);
  356.         if ($this->isCsrfTokenValid('delete'.$product->getId(), $request->request->get('_token'))) {
  357.             $entityManager $this->getDoctrine()->getManager();
  358.             $entityManager->remove($product);
  359.             $entityManager->flush();
  360.             $this->addFlash('success''Product deleted.');
  361.             $this->redirectToRoute('product_index');
  362.         }
  363.         if ($form->isSubmitted() && $form->isValid()) {
  364.             //dd($form->getData());
  365.             /*  $customFields = $product->getProductType()->getProductTypeFields()->getValues();
  366.               foreach ($customFields as $field){
  367.                   //$field->getName();
  368.                   //$form->get($field->getName())->getData();
  369.                   //$productField = $productFieldRepository->find();
  370.               }*/
  371.             $form->getData();
  372.             $this->getDoctrine()->getManager()->flush();
  373.             $this->addFlash('success''Product updated.');
  374.             return $this->redirectToRoute('product_index');
  375.         }
  376.         return $this->render('product/edit_test.html.twig', [
  377.             'product' => $product,
  378.             'form' => $form->createView(),
  379.         ]);
  380.     }
  381.     /**
  382.      * @Route("/search_product", methods="GET", name="product_search_select2", options={"expose"=true})
  383.      */
  384.     public function productSearchSelect2(Request $requestProductRepository $products): JsonResponse
  385.     {
  386.         $query $request->query->get('q''');
  387.         $foundProducts $products->findByNameOrCode($query);
  388.         $results = [];
  389.         foreach ($foundProducts as $product) {
  390.             /* @var $product Product */
  391.             $results['results'][] = [
  392.                 'id' => htmlspecialchars($product->getId(), \ENT_COMPAT | \ENT_HTML5),
  393.                 'text' => htmlspecialchars('[' $product->getCode() . '] ' $product->getName(),
  394.                     \ENT_COMPAT | \ENT_HTML5)
  395.             ];
  396.         }
  397.         return $this->json($results);
  398.     }
  399.     /**
  400.      * @Route ("/get_incoming_orders", methods="GET", name="get_incoming_orders")
  401.      */
  402.     public function get_incoming_orders(IncomingOrderRepository $incomingOrderRepository): JsonResponse
  403.     {
  404.         //Get incoming pending orders
  405.         //$incomingOrders =
  406.         return $this->json($incomingOrderRepository->findBy(
  407.             ['status' => 'pending']
  408.         ),
  409.             200,
  410.             [],
  411.             ['groups' => 'list_incoming_order']
  412.         );
  413.     }
  414.     /**
  415.      * @Route("/add_to_incoming_order", methods={"GET","POST","PUT"}, name="add_to_incoming_order")
  416.      *
  417.      */
  418.     function add_to_incoming_order(Request $requestProductRepository $productRepository,
  419.        IncomingOrderRepository $incomingOrderRepositoryEntityManagerInterface $entityManager
  420.     ):Response
  421.     {
  422.         if ($request->isXmlHttpRequest()){
  423.             $result = [
  424.                 'result' => 'failed'
  425.             ];
  426.             $incomingOrderId $request->request->get('incoming_order_id');
  427.             $incomingOrder $incomingOrderRepository->find($incomingOrderId);
  428.             if ($incomingOrder){
  429.                 //see if it's all selected or checkbox selected.
  430.                 $selectAll $request->request->get('selectAll');
  431.                 if ($selectAll == 1){
  432.                     $queryParams $this->get_params_from_search_query($request);
  433.                     $products $productRepository->findBySearchQuery($queryParams)->execute();
  434.                 }else{
  435.                     //get checkbox values
  436.                     $checkedProductIds $request->request->get('product_ids');
  437.                     $products $productRepository->findBy(['id' => $checkedProductIds]);
  438.                 }
  439.                 if (count($products) > 50){
  440.                     $result = [
  441.                         'result' => 'fail',
  442.                         'msg' => 'Sorry, you cannot add more than 50 records to the order.'
  443.                     ];
  444.                 }else{
  445.                     $productCnt 0;
  446.                     foreach ($products as $product){
  447.                         if (is_array($product)){
  448.                             $product $product[0];
  449.                         }
  450.                         $productIn = new ProductIn();
  451.                         $productIn->setIncomingOrder($incomingOrder);
  452.                         $productIn->setProduct($product);
  453.                         $productQty $product->getQty();
  454.                         $productHoldQty $product->getHold();
  455.                         //$productInOrderQty = 0;
  456.                         $productInOrderQty $productHoldQty $productQty;
  457.                         $productIn->setQty($productInOrderQty);
  458.                         $entityManager->persist($productIn);
  459.                         $productCnt++;
  460.                     }
  461.                     $entityManager->flush();
  462.                     $result = [
  463.                         'result' => 'success',
  464.                         'msg' => $productCnt. ($productCnt>1?' products':' product').' added to the order.'
  465.                     ];
  466.                 }
  467.             }
  468.             return $this->json($result);
  469.         }
  470.         return new Response('This is not ajax!'400);
  471.     }
  472.     private function get_params_from_search_query($request)
  473.     {
  474.         $result = [];
  475.         $result['code'] = trim($request->query->get('code'));
  476.         $result['name'] = trim($request->query->get('name'));
  477.         $result['description'] = trim($request->query->get('description'));
  478.         $result['qty_comparison'] = trim($request->query->get('qty_comparison'));
  479.         $result['qty'] = trim($request->query->get('qty'));
  480.         $result['price_comparison'] = trim($request->query->get('price_comparison'));
  481.         $result['price'] = trim($request->query->get('price'));
  482.         $result['shop_stock'] = trim($request->query->get('shop_stock'));
  483.         $result['hold'] = trim($request->query->get('hold'));
  484.         $result['hold_comparison'] = trim($request->query->get('hold_comparison'));
  485.         $result['less_than_hold'] = trim($request->query->get('less_than_hold'));
  486.         $result['product_type_id'] = trim($request->query->get('product_type_id'));
  487.         //Additional fields
  488.         /* @var $request Request */
  489.         $queries $request->query->all();
  490.         foreach ($queries as $key => $val){
  491.             if (in_array($key,Product::ADDITIONAL_FIELDS)){
  492.                 $result[$key] = $val;
  493.             }
  494.         }
  495.         return $result;
  496.     }
  497. }