src/Controller/PurchaseOrderController.php line 412

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\PurchaseOrder;
  4. use App\Entity\SalesCase;
  5. use App\Entity\Supplier;
  6. use App\Exception\AccessDeniedException;
  7. use App\Exception\CurrencyException;
  8. use App\Form\Type\DocumentNotesType;
  9. use App\Form\Type\LogEntryType;
  10. use App\Form\Type\PurchaseOrderType;
  11. use App\Repository\ProductConfigurationItemRepository;
  12. use App\Service\ProductService;
  13. use App\Service\PurchaseOrderService;
  14. use Exception;
  15. use Symfony\Component\HttpFoundation\RedirectResponse;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\HttpFoundation\JsonResponse;
  18. use Symfony\Component\HttpFoundation\Response;
  19. use Symfony\Component\HttpKernel\Profiler\Profiler;
  20. use Symfony\Component\Routing\Annotation\Route;
  21. class PurchaseOrderController extends AbstractController
  22. {
  23.     /**
  24.      * @var ProductConfigurationItemRepository
  25.      */
  26.     protected ProductConfigurationItemRepository $productConfigurationItemRepository;
  27.     /**
  28.      * @var ProductService
  29.      */
  30.     protected ProductService $productService;
  31.     /**
  32.      * @var PurchaseOrderService
  33.      */
  34.     protected PurchaseOrderService $purchaseOrderService;
  35.     /**
  36.      * @param PurchaseOrderService $purchaseOrderService
  37.      * @param ProductService $productService
  38.      * @param ProductConfigurationItemRepository $productConfigurationItemRepository
  39.      */
  40.     public function __construct(
  41.         PurchaseOrderService $purchaseOrderService,
  42.         ProductService $productService,
  43.         ProductConfigurationItemRepository $productConfigurationItemRepository
  44.     ) {
  45.         $this->purchaseOrderService $purchaseOrderService;
  46.         $this->productService $productService;
  47.         $this->productConfigurationItemRepository $productConfigurationItemRepository;
  48.     }
  49.     /**
  50.      * @Route(
  51.      *     "/cases/{salesCase}/purchase-orders/create/{supplier}",
  52.      *     name="app.purchase_order.create",
  53.      *     requirements={"salesCase" = "\d+", "supplier" = "\d+"}
  54.      * )
  55.      *
  56.      * @param SalesCase $salesCase
  57.      * @param Supplier  $supplier
  58.      *
  59.      * @return RedirectResponse
  60.      */
  61.     public function createAction(SalesCase $salesCaseSupplier $supplier): RedirectResponse
  62.     {
  63.         try {
  64.             $salesItems = [];
  65.             if (null !== $orderConfirmation $salesCase->getOrderConfirmation()) {
  66.                 $orderConfirmationSalesItems $orderConfirmation->getSalesItems();
  67.                 foreach ($orderConfirmationSalesItems as $item) {
  68.                     if ($item->getSupplier() === $supplier) {
  69.                         if ($item->isPciSubItem()) {
  70.                             $item = clone $item;
  71.                             $pciPosition $item->getPciPosition();
  72.                             foreach ($orderConfirmationSalesItems as $itemTemp) {
  73.                                 if ($itemTemp->getPosition() == $pciPosition) {
  74.                                     $item->setQuantity($itemTemp->getQuantity() * $item->getQuantity());
  75.                                 }
  76.                             }
  77.                         }
  78.                         $salesItems[] = $item;
  79.                     }
  80.                 }
  81.             }
  82.             $purchaseOrder $this->purchaseOrderService->getNew(
  83.                 $salesCase,
  84.                 $supplier,
  85.                 $salesItems
  86.             );
  87.             $this->purchaseOrderService->assertInventoryBalanceNotExceeded($purchaseOrder);
  88.             $this->purchaseOrderService->create($purchaseOrder);
  89.             $this->flashSuccess('entity.success.create', [], 'PurchaseOrder');
  90.             if (null === $purchaseOrder->getInvoicingAddress()) {
  91.                 $this->flashWarning('entity.error.no_inventory_address', [], 'PurchaseOrder');
  92.             }
  93.             return $this->redirectResponse(
  94.                 'app.purchase_order.update',
  95.                 [
  96.                     'purchaseOrder' => $purchaseOrder->getId(),
  97.                 ]
  98.             );
  99.         } catch (Exception $e) {
  100.             $this->flashError('entity.error.create', [], 'PurchaseOrder');
  101.             if ($this->getCurrentUser()->isSuperAdmin()) {
  102.                 $this->flashError($e->getMessage());
  103.             }
  104.         }
  105.         return $this->redirectResponse(
  106.             'app.sales_case.order_confirmation.update',
  107.             [
  108.                 'salesCase' => $salesCase->getId(),
  109.             ]
  110.         );
  111.     }
  112.     /**
  113.      * @Route(
  114.      *     "/cases/{salesCase}/purchase-orders/create-all",
  115.      *     name="app.purchase_order.create_all",
  116.      *     requirements={"salesCase" = "\d+"}
  117.      * )
  118.      *
  119.      * @param SalesCase $salesCase
  120.      *
  121.      * @return RedirectResponse
  122.      */
  123.     public function createAllAction(SalesCase $salesCase): RedirectResponse
  124.     {
  125.         try {
  126.             $purchaseOrders $this->purchaseOrderService->getNewAll($salesCase);
  127.             foreach ($purchaseOrders as $purchaseOrder) {
  128.                 $this->purchaseOrderService->assertInventoryBalanceNotExceeded($purchaseOrder);
  129.                 $this->purchaseOrderService->create($purchaseOrder);
  130.             }
  131.             $this->flashSuccess(
  132.                 'entity.success.create_all',
  133.                 [
  134.                     '%list%' => implode(
  135.                         ', ',
  136.                         array_map(
  137.                             function (PurchaseOrder $purchaseOrder) {
  138.                                 return $purchaseOrder->getNumber();
  139.                             },
  140.                             $purchaseOrders
  141.                         )
  142.                     ),
  143.                 ],
  144.                 'PurchaseOrder'
  145.             );
  146.         } catch (Exception $e) {
  147.             $this->flashError('entity.error.create_all', [], 'PurchaseOrder');
  148.             if ($this->getCurrentUser()->isSuperAdmin()) {
  149.                 $this->flashError($e->getMessage());
  150.             }
  151.         }
  152.         return $this->redirectResponse(
  153.             'app.sales_case.order_confirmation.update',
  154.             [
  155.                 'salesCase' => $salesCase->getId(),
  156.             ]
  157.         );
  158.     }
  159.     /**
  160.      * @Route(
  161.      *     "/purchase-orders/{purchaseOrder}/delete",
  162.      *     name="app.purchase_order.delete",
  163.      *     requirements={"purchaseOrder" = "\d+"}
  164.      * )
  165.      *
  166.      * @param PurchaseOrder $purchaseOrder
  167.      *
  168.      * @return RedirectResponse
  169.      *
  170.      * @throws AccessDeniedException
  171.      */
  172.     public function deleteAction(PurchaseOrder $purchaseOrder): RedirectResponse
  173.     {
  174.         $this->purchaseOrderService->assertDelete($purchaseOrder);
  175.         try {
  176.             $this->purchaseOrderService->delete($purchaseOrder);
  177.             $this->flashSuccess('entity.success.delete', [], 'PurchaseOrder');
  178.         } catch (Exception $e) {
  179.             $this->flashError('entity.error.delete', [], 'PurchaseOrder');
  180.             if ($this->getCurrentUser()->isSuperAdmin()) {
  181.                 $this->flashError($e->getMessage());
  182.             }
  183.         }
  184.         return $this->redirectResponse(
  185.             'app.sales_case.order_confirmation.update',
  186.             [
  187.                 'salesCase' => $purchaseOrder->getSalesCase()->getId(),
  188.             ]
  189.         );
  190.     }
  191.     /**
  192.      * @Route(
  193.      *     "/purchase-orders/{purchaseOrder}/pdf",
  194.      *     name="app.purchase_order.pdf",
  195.      *     requirements={"purchaseOrder" = "\d+"}
  196.      * )
  197.      *
  198.      * @param PurchaseOrder $purchaseOrder
  199.      * @param Profiler|null $profiler
  200.      *
  201.      * @return Response
  202.      */
  203.     public function getPdf(PurchaseOrder $purchaseOrder, ?Profiler $profiler): Response
  204.     {
  205.         $profiler?->disable();
  206.         try {
  207.             return new Response(
  208.                 $this->purchaseOrderService->generatePdf($purchaseOrder),
  209.                 200,
  210.                 [
  211.                     'Content-Type' => 'application/pdf',
  212.                     'Content-Disposition' => 'attachment; filename="' $purchaseOrder->getPreviewFileName() . '"',
  213.                 ]
  214.             );
  215.         } catch (Exception $e) {
  216.             $this->flashError('Failed to generate the purchase order PDF.');
  217.             $this->flashError($e->getMessage());
  218.         }
  219.         return $this->redirectResponse(
  220.             'app.purchase_order.update',
  221.             [
  222.                 'purchaseOrder' => $purchaseOrder->getId(),
  223.             ]
  224.         );
  225.     }
  226.     /**
  227.      * @Route(
  228.      *     "/price-updates",
  229.      *     name="app.purchase_order.price_updates"
  230.      * )
  231.      *
  232.      * @return Response
  233.      */
  234.     public function priceUpdatesAction(): Response
  235.     {
  236.         return $this->render(
  237.             'Product/priceUpdates.html.twig',
  238.             [
  239.                 'priceUpdates' => $this->purchaseOrderService->getPriceUpdates(),
  240.             ]
  241.         );
  242.     }
  243.     /**
  244.      * @Route(
  245.      *     "/purchase-orders/{purchaseOrder}/versions/create",
  246.      *     name="app.rest.purchase_order.version.create",
  247.      *     requirements={"purchaseOrder" = "\d+"}
  248.      * )
  249.      *
  250.      * @param PurchaseOrder $purchaseOrder
  251.      *
  252.      * @return JsonResponse
  253.      */
  254.     public function restCreateDocumentVersionAction(PurchaseOrder $purchaseOrder): JsonResponse
  255.     {
  256.         $data = [];
  257.         try {
  258.             $this->purchaseOrderService->assertUpdate($purchaseOrder);
  259.             $documentVersion $this->purchaseOrderService->generateVersion($purchaseOrder);
  260.             $data['row'] = $this->renderView(
  261.                 'Document/versionRow.html.twig',
  262.                 [
  263.                     'version' => $documentVersion,
  264.                 ]
  265.             );
  266.         } catch (Exception $e) {
  267.             $data['error'] = 'Failed to create the document version.';
  268.         }
  269.         return new JsonResponse($data);
  270.     }
  271.     /**
  272.      * @Route(
  273.      *     "/purchase-orders/{purchaseOrder}/notes/update",
  274.      *     name="app.rest.purchase_order.notes.update",
  275.      *     requirements={"purchaseOrder" = "\d+"}
  276.      * )
  277.      *
  278.      * @param Request       $request
  279.      * @param PurchaseOrder $purchaseOrder
  280.      *
  281.      * @return JsonResponse
  282.      */
  283.     public function restUpdateNotesAction(Request $requestPurchaseOrder $purchaseOrder): JsonResponse
  284.     {
  285.         $data = [
  286.             'success' => true,
  287.             'notes'   => null,
  288.         ];
  289.         try {
  290.             $this->purchaseOrderService->assertUpdate($purchaseOrder);
  291.             $notesForm $this->createForm(
  292.                 DocumentNotesType::class,
  293.                 $purchaseOrder,
  294.                 [
  295.                     'action' => $this->generateUrl(
  296.                         'app.rest.purchase_order.notes.update',
  297.                         [
  298.                             'purchaseOrder' => $purchaseOrder->getId(),
  299.                         ]
  300.                     ),
  301.                 ]
  302.             );
  303.             $notesForm->handleRequest($request);
  304.             if ($notesForm->isSubmitted()) {
  305.                 if ($notesForm->isValid()) {
  306.                     $this->purchaseOrderService->update($purchaseOrder);
  307.                     $data['notes'] = $purchaseOrder->getNotes();
  308.                 }
  309.             }
  310.         } catch (Exception $e) {
  311.             $data['success'] = false;
  312.             $data['error'] = 'Failed to update the purchase order notes.';
  313.         }
  314.         return new JsonResponse($data);
  315.     }
  316.     /**
  317.      * @Route(
  318.      *     "/purchase-orders/{purchaseOrder}/status/update",
  319.      *     name="app.rest.purchase_order.status.update",
  320.      *     requirements={"purchaseOrder" = "\d+"}
  321.      * )
  322.      *
  323.      * @param Request       $request
  324.      * @param PurchaseOrder $purchaseOrder
  325.      *
  326.      * @return JsonResponse
  327.      */
  328.     public function restUpdateStatusAction(Request $requestPurchaseOrder $purchaseOrder): JsonResponse
  329.     {
  330.         $data = [
  331.             'success' => true,
  332.         ];
  333.         try {
  334.             $this->purchaseOrderService->assertUpdate($purchaseOrder);
  335.             $status $request->query->get('status');
  336.             $this->purchaseOrderService->updateStatus($purchaseOrder$status);
  337.             $data['status'] = $purchaseOrder->getStatus();
  338.             $data['number'] = $purchaseOrder->getNumber();
  339.             $data['dropdown'] = $this->renderView(
  340.                 'Document/documentDropdown.html.twig',
  341.                 [
  342.                     'salesCase' => $purchaseOrder->getSalesCase(),
  343.                 ]
  344.             );
  345.             $data['versions'] = $this->renderView(
  346.                 'Document/documentVersions.html.twig',
  347.                 [
  348.                     'versions' => $purchaseOrder->getDocumentVersions(),
  349.                     'url'      => $this->generateUrl('app.purchase_order.pdf', ['purchaseOrder' => $purchaseOrder->getId()]),
  350.                     'draft'    => $purchaseOrder->isDraft(),
  351.                 ]
  352.             );
  353.             $data['versionsModal'] = $this->renderView(
  354.                 'Document/documentVersionsModal.html.twig',
  355.                 [
  356.                     'versions' => $purchaseOrder->getDocumentVersions(),
  357.                     'url'      => $this->generateUrl('app.rest.purchase_order.version.create', ['purchaseOrder' => $purchaseOrder->getId()]),
  358.                 ]
  359.             );
  360.         } catch (Exception $e) {
  361.             $data['success'] = false;
  362.             $data['error'] = 'Failed to update the purchase order status.';
  363.         }
  364.         return new JsonResponse($data);
  365.     }
  366.     /**
  367.      * @Route(
  368.      *     "/purchase-orders/{purchaseOrder}/update",
  369.      *     name="app.purchase_order.update",
  370.      *     requirements={"purchaseOrder" = "\d+"}
  371.      * )
  372.      *
  373.      * @param Request $request
  374.      * @param PurchaseOrder $purchaseOrder
  375.      *
  376.      * @return Response
  377.      *
  378.      * @throws AccessDeniedException
  379.      * @throws CurrencyException
  380.      */
  381.     public function updateAction(Request $requestPurchaseOrder $purchaseOrder): Response
  382.     {
  383.         $this->purchaseOrderService->assertRead($purchaseOrder);
  384.         $this->productService->populateLimitedAvailability($purchaseOrder);
  385.         $form $this->createForm(
  386.             PurchaseOrderType::class,
  387.             $purchaseOrder,
  388.             [
  389.                 'action' => $this->generateUrl(
  390.                     'app.purchase_order.update',
  391.                     [
  392.                         'purchaseOrder' => $purchaseOrder->getId()
  393.                     ]
  394.                 ),
  395.                 'disabled' => ! $this->purchaseOrderService->canUpdate($purchaseOrder)
  396.             ]
  397.         );
  398.         $notesForm $this->createForm(
  399.             DocumentNotesType::class,
  400.             $purchaseOrder,
  401.             [
  402.                 'action' => $this->generateUrl(
  403.                     'app.rest.purchase_order.notes.update',
  404.                     [
  405.                         'purchaseOrder' => $purchaseOrder->getId(),
  406.                     ]
  407.                 ),
  408.             ]
  409.         );
  410.         $logEntryFormView null;
  411.         $form->handleRequest($request);
  412.         if ($form->isSubmitted()) {
  413.             if ($form->isValid()) {
  414.                 try {
  415.                     $this->purchaseOrderService->assertInventoryBalanceNotExceeded($purchaseOrder);
  416.                     $this->purchaseOrderService->update($purchaseOrder);
  417.                     $logEntry $purchaseOrder->getLastLogEntry();
  418.                     $logEntryForm $this->createForm(
  419.                         LogEntryType::class,
  420.                         $logEntry,
  421.                         [
  422.                             'action' => $this->generateUrl(
  423.                                 'app.rest.log_entry.update',
  424.                                 [
  425.                                     'logEntry' => $logEntry->getId(),
  426.                                 ]
  427.                             ),
  428.                         ]
  429.                     );
  430.                     $logEntryFormView $logEntryForm->createView();
  431.                     $this->flashSuccess('entity.success.update', [], 'PurchaseOrder');
  432.                 } catch (Exception $e) {
  433.                     $this->flashError('entity.error.update', [], 'PurchaseOrder');
  434.                     if ($this->getCurrentUser()->isSuperAdmin()) {
  435.                         $this->flashError($e->getMessage());
  436.                     }
  437.                 }
  438.             } else {
  439.                 $this->flashError('entity.error.validate', [], 'PurchaseOrder');
  440.             }
  441.         }
  442.         return $this->render(
  443.             'PurchaseOrder/update.html.twig',
  444.             [
  445.                 'salesCase' => $purchaseOrder->getSalesCase(),
  446.                 'purchaseOrder' => $purchaseOrder,
  447.                 'form' => $form->createView(),
  448.                 'logEntryForm' => $logEntryFormView,
  449.                 'notesForm' => $notesForm->createView(),
  450.                 'salesItemUpdates' => $this->purchaseOrderService->getPriceUpdatesForPurchaseOrder($purchaseOrder),
  451.                 'productConfigurationItems' => $this->productConfigurationItemRepository->findAll(),
  452.             ]
  453.         );
  454.     }
  455. }