src/Controller/OrderController.php line 1463

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller;
  4. use App\Entity\Customer\Customer;
  5. use App\Entity\Order\Order;
  6. use App\Entity\Order\OrderItem;
  7. use App\Entity\Order\OrderItemCancellation;
  8. use App\Entity\Order\OrderItemRequirement;
  9. use App\Entity\Order\OrderItemReservation;
  10. use App\Entity\Order\OrderNature;
  11. use App\Entity\Order\OrderState;
  12. use App\Entity\Order\OrderType;
  13. use App\Entity\Product\Depot;
  14. use App\Entity\Product\Product;
  15. use App\Form\Type\Order as TypeOrder;
  16. use App\Service\ProductService;
  17. use Pagerfanta\Adapter\ArrayAdapter;
  18. use Pagerfanta\Pagerfanta;
  19. use Sylius\Bundle\OrderBundle\Controller\OrderController as BaseOrderController;
  20. use Sylius\Bundle\ResourceBundle\Grid\View\ResourceGridView;
  21. use Sylius\Component\Resource\ResourceActions;
  22. use Symfony\Component\HttpFoundation\Request;
  23. use Symfony\Component\HttpFoundation\Response;
  24. use Sylius\Component\Grid\Parameters;
  25. use Sylius\Component\Order\Model\OrderItemInterface;
  26. use Sylius\Component\Product\Model\ProductInterface;
  27. use Symfony\Component\HttpFoundation\JsonResponse;
  28. use ApiPlatform\Core\Api\IriConverterInterface;
  29. use App\Entity\Taxation\TaxRate;
  30. use App\Service\OrderService;
  31. use Doctrine\ORM\EntityManagerInterface;
  32. use Doctrine\ORM\Tools\Pagination\Paginator;
  33. use Pagerfanta\Adapter\DoctrineORMAdapter;
  34. use Sylius\Component\Core\Model\ProductVariantInterface;
  35. use Sylius\Component\Order\Model\OrderInterface;
  36. use Symfony\Component\HttpFoundation\File\UploadedFile;
  37. class OrderController extends BaseOrderController
  38. {
  39.     protected $searchService;
  40.     protected $orderService;
  41.     protected $ftpLogService;
  42.     public function indexAction(Request $request): Response
  43.     {
  44.  error_log('indexAction called');
  45.     // 1. Configuration et permissions (obligatoire, on ne peut pas l'éviter)
  46.     $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  47.     $this->isGrantedOr403($configurationResourceActions::INDEX);
  48.     // 2. Récupération des services (mise en cache si possible dans le constructeur)
  49.     $this->orderService $this->orderService ?? $this->container->get(OrderService::class);
  50.     // 3. Extraction des paramètres (optimisé avec des valeurs par défaut)
  51.     $route $request->get('_route');
  52.     $fromCustomerId = ($route === 'sylius_admin_customer_order_index') ? (int)$request->get('id') : 0;
  53.     // 4. Gestion des filtres avec valeur par défaut (une seule fois)
  54.     $filters $request->query->get('criteria', []);
  55.     if(empty($filters) && empty($fromCustomerId)){$filters['orderState'] = 310;$filters['orderType'] = 3;}
  56.     if (empty($filters['date']) && empty($fromCustomerId)) {$filters['createdAt'] = ['from' => (new \DateTimeImmutable('-60 days'))->format('Y-m-d')];
  57.     }else{
  58.      $filters['createdAt'] = [
  59.     'from' => $filters['date']['from']['date'] ?? null,
  60.     'to'   => $filters['date']['to']['date']   ?? null,
  61. ];
  62.     }
  63.     // 5. Création du QueryBuilder (une seule fois, pas de double requête)
  64.     $qb $this->orderService->createFilteredOrderQBuilder($filters$fromCustomerId);
  65.     // 6. Application du tri (optimisé avec array_walk pour éviter les boucles)
  66.     $sorting $request->query->get('sorting', ['createdAt' => 'desc']);
  67.     array_walk($sorting, function($direction$field) use ($qb) {
  68.         $qb->addOrderBy('o.' $field$direction);
  69.     });
  70.     // 7. Paramètres de pagination
  71.     $page = (int)$request->query->get('page'1);
  72.     $limit = (int)$request->query->get('limit'50);
  73.     // 8. OPTIMISATION MAJEURE : Utilisation d'un seul adapter optimisé
  74.     // Le troisième paramètre (true) active l'output walker pour une meilleure performance
  75.     // sur les requêtes complexes avec jointures
  76.     $adapter = new DoctrineORMAdapter($qbtruetrue);
  77.     $pagerfanta = new Pagerfanta($adapter);
  78.     $pagerfanta->setMaxPerPage($limit);
  79.     try {
  80.         $pagerfanta->setCurrentPage($page);
  81.     } catch (\OutOfRangeException $e) {
  82.         $pagerfanta->setCurrentPage(1);
  83.     }
  84.     // 9. OPTIMISATION : Récupération des données une seule fois
  85.     // On récupère les orders depuis Pagerfanta au lieu de faire une double requête
  86.     $orders $pagerfanta->getCurrentPageResults();
  87.     // 10. Calcul optimisé du nombre total (utilise le count du QueryBuilder)
  88.     $totalHits $pagerfanta->getNbResults();
  89.     $totalPages $pagerfanta->getNbPages();
  90.     // 11. Grid definition (mise en cache possible dans le constructeur)
  91.     $gridProvider $this->gridProvider ?? $this->container->get('sylius.grid.provider');
  92.     $gridDefinition $gridProvider->get('sylius_admin_order');
  93.     // 12. Création de la vue
  94.     $resourceGridView = new ResourceGridView(
  95.         $pagerfanta,
  96.         $gridDefinition,
  97.         new Parameters($request->query->all()),
  98.         $this->metadata,
  99.         $configuration
  100.     );
  101.     // 13. Dispatch des événements (seulement si nécessaire)
  102.     if ($this->eventDispatcher) {
  103.         $this->eventDispatcher->dispatchMultiple(ResourceActions::INDEX$configuration$orders);
  104.     }
  105.     error_log('totalHits: ' $totalHits);
  106.     error_log('totalPages: ' $totalPages);
  107.     // 14. Rendu de la réponse
  108.     if ($configuration->isHtmlRequest()) {
  109.         return $this->render($configuration->getTemplate(ResourceActions::INDEX '.html'), [
  110.             'configuration' => $configuration,
  111.             'metadata' => $this->metadata,
  112.             'resources' => $resourceGridView,
  113.             $this->metadata->getPluralName() => $resourceGridView,
  114.             'totalHits' => $totalHits,
  115.             'totalPages' => $totalPages,
  116.         ]);
  117.     }
  118.     return $this->createRestView($configuration$orders);
  119. // $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
  120. // $this->isGrantedOr403($configuration, ResourceActions::INDEX);
  121. // $gridProvider = $this->container->get('sylius.grid.provider');
  122. // $grid = $gridProvider->get('sylius_admin_order');
  123. // // 1. Récupérer tous les paramètres de la requête UNE SEULE FOIS
  124. // $parameters = $request->query->all();
  125. // // 2. Appliquer la limite par défaut SI elle n'est pas déjà dans l'URL
  126. // if (!isset($parameters['limit'])) {
  127. //     $parameters['limit'] = 50;
  128. // }
  129. // // 3. Appliquer le filtre de date par défaut SI aucun filtre de date n'est déjà appliqué
  130. // $criteria = $parameters['criteria'] ?? [];
  131. // $hasUserDate = (!empty($criteria['createdAt']['from'])) || (!empty($criteria['createdAt']['to']));
  132. // if (!$hasUserDate) {
  133. //     // On s'assure que le tableau imbriqué existe avant d'assigner
  134. //     $parameters['criteria']['createdAt']['from'] = (new \DateTime('-2 months'))->format('Y-m-d');
  135. // }
  136. // // 4. (optionnel) Ajouter le filtre client depuis la route
  137. // $route = $request->get('_route');
  138. // $fromCustomerId = $route === 'sylius_admin_customer_order_index' ? (int) $request->get('id') : null;
  139. // if ($fromCustomerId) {
  140. //     // Cela va écraser un éventuel filtre client venant de l'URL, ce qui est le comportement attendu ici
  141. //     $parameters['criteria']['customer'] = ['value' => $fromCustomerId];
  142. // }
  143. // // 5. Créer l'objet Parameters une seule fois avec tous les bons paramètres
  144. // $finalParams = new Parameters($parameters);
  145. // /** @var ResourceGridViewFactoryInterface $factory */
  146. // $factory = $this->container->get('sylius.grid.resource_view_factory');
  147. // $resourceGridView = $factory->create($grid, $finalParams, $this->metadata, $configuration);
  148. // if ($configuration->isHtmlRequest()) {
  149. //     return $this->render($configuration->getTemplate(ResourceActions::INDEX . '.html'), [
  150. //         'configuration' => $configuration,
  151. //         'metadata'      => $this->metadata,
  152. //         'resources'     => $resourceGridView,
  153. //         $this->metadata->getPluralName() => $resourceGridView,
  154. //     ]);
  155. // }
  156. // return $this->createRestView($configuration, iterator_to_array($resourceGridView->getData()));
  157.         // error_log('indexAction called');
  158.         // $configuration = $this->requestConfigurationFactory->create($this->metadata, $request);
  159.         // $this->isGrantedOr403($configuration, ResourceActions::INDEX);
  160.         // // Get order service from container
  161.         // $this->orderService = $this->container->get(OrderService::class);
  162.         // $route = $request->get('_route');
  163.         // $fromCustomerId = $route  == 'sylius_admin_customer_order_index' ? $request->get('id') : 0;
  164.         // // Use the service to get paginated orders
  165.         // $result = $this->orderService->getPaginatedOrders($request, $fromCustomerId);
  166.         // $orders = $result['orders'];
  167.         // $totalHits = $result['totalHits'];
  168.         // $totalPages = $result['totalPages'];
  169.         // // Create query builder for Pagerfanta
  170.         // $filters = $request->query->get('criteria', []);
  171.         // $qb = $this->orderService->createFilteredOrderQueryBuilder($filters, $fromCustomerId);
  172.         // // Apply sorting
  173.         // $sorting = $request->query->get('sorting', ['createdAt' => 'desc']);
  174.         // foreach ($sorting as $field => $direction) {
  175.         //     $qb->addOrderBy('o.' . $field, $direction);
  176.         // }
  177.         // // Create Pagerfanta object for pagination
  178.         // $page = $request->query->get('page', 1);
  179.         // $limit = $request->query->get('limit', 50);
  180.         // $adapter = new DoctrineORMAdapter($qb, false, false);
  181.         // $pagerfanta = new Pagerfanta($adapter);
  182.         // $pagerfanta->setMaxPerPage($limit);
  183.         // $pagerfanta->setCurrentPage($page);
  184.         // $pagerfanta->setMaxNbPages((int)$totalPages);
  185.         // // Get grid definition from the configuration
  186.         // $gridDefinition = $this->container->get('sylius.grid.provider')->get('sylius_admin_order');
  187.         // // Create ResourceGridView object
  188.         // $resourceGridView = new ResourceGridView(
  189.         //     $pagerfanta,
  190.         //     $gridDefinition,
  191.         //     new Parameters($request->query->all()),
  192.         //     $this->metadata,
  193.         //     $configuration
  194.         // );
  195.         // $this->eventDispatcher->dispatchMultiple(ResourceActions::INDEX, $configuration, $orders);
  196.         // error_log('totalHits: ' . $totalHits);
  197.         // error_log('totalPages: ' . $totalPages);
  198.         // if ($configuration->isHtmlRequest()) {
  199.         //     return $this->render($configuration->getTemplate(ResourceActions::INDEX . '.html'), [
  200.         //         'configuration' => $configuration,
  201.         //         'metadata' => $this->metadata,
  202.         //         'resources' => $resourceGridView,
  203.         //         $this->metadata->getPluralName() => $resourceGridView,
  204.         //         'totalHits' => $totalHits,
  205.         //         'totalPages' => $totalPages,
  206.         //     ]);
  207.     }
  208.     private function initializeServices(): void
  209. {
  210.     // Pré-charger les services
  211.     $this->orderService $this->container->get(OrderService::class);
  212.     $this->gridProvider $this->container->get('sylius.grid.provider');
  213. }
  214. public function indexActionWithCache(Request $request): Response
  215. {
  216.     error_log('indexAction called');
  217.     $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  218.     $this->isGrantedOr403($configurationResourceActions::INDEX);
  219.     $this->orderService $this->orderService ?? $this->container->get(OrderService::class);
  220.     $route $request->get('_route');
  221.     $fromCustomerId = ($route === 'sylius_admin_customer_order_index') ? (int)$request->get('id') : 0;
  222.     $filters $request->query->get('criteria', []);
  223.     if (empty($filters['createdAt']) && empty($fromCustomerId)) {
  224.         $filters['createdAt'] = [
  225.             'from' => (new \DateTimeImmutable('-90 days'))->format('Y-m-d')
  226.         ];
  227.     }
  228.     // Création d'une clé de cache unique basée sur les paramètres
  229.     $cacheKey md5(serialize([
  230.         'filters' => $filters,
  231.         'customer' => $fromCustomerId,
  232.         'sorting' => $request->query->get('sorting', ['createdAt' => 'desc']),
  233.         'page' => $request->query->get('page'1),
  234.         'limit' => $request->query->get('limit'50)
  235.     ]));
  236.     $qb $this->orderService->createFilteredOrderQBuilder($filters$fromCustomerId);
  237.     // Active le cache de requête Doctrine (60 secondes)
  238.     $qb->getQuery()
  239.        ->useResultCache(true60'orders_' $cacheKey)
  240.        ->useQueryCache(true);
  241.     $sorting $request->query->get('sorting', ['createdAt' => 'desc']);
  242.     array_walk($sorting, function($direction$field) use ($qb) {
  243.         $qb->addOrderBy('o.' $field$direction);
  244.     });
  245.     $page = (int)$request->query->get('page'1);
  246.     $limit = (int)$request->query->get('limit'50);
  247.     // Utilisation de l'adapter optimisé avec hydratation partielle si possible
  248.     $adapter = new DoctrineORMAdapter($qbtruetrue);
  249.     $pagerfanta = new Pagerfanta($adapter);
  250.     $pagerfanta->setMaxPerPage($limit);
  251.     try {
  252.         $pagerfanta->setCurrentPage($page);
  253.     } catch (\OutOfRangeException $e) {
  254.         $pagerfanta->setCurrentPage(1);
  255.     }
  256.     $orders $pagerfanta->getCurrentPageResults();
  257.     $totalHits $pagerfanta->getNbResults();
  258.     $totalPages $pagerfanta->getNbPages();
  259.     $gridProvider $this->gridProvider ?? $this->container->get('sylius.grid.provider');
  260.     $gridDefinition $gridProvider->get('sylius_admin_order');
  261.     $resourceGridView = new ResourceGridView(
  262.         $pagerfanta,
  263.         $gridDefinition,
  264.         new Parameters($request->query->all()),
  265.         $this->metadata,
  266.         $configuration
  267.     );
  268.     if ($this->eventDispatcher) {
  269.         $this->eventDispatcher->dispatchMultiple(ResourceActions::INDEX$configuration$orders);
  270.     }
  271.     error_log('totalHits: ' $totalHits);
  272.     error_log('totalPages: ' $totalPages);
  273.     if ($configuration->isHtmlRequest()) {
  274.         return $this->render($configuration->getTemplate(ResourceActions::INDEX '.html'), [
  275.             'configuration' => $configuration,
  276.             'metadata' => $this->metadata,
  277.             'resources' => $resourceGridView,
  278.             $this->metadata->getPluralName() => $resourceGridView,
  279.             'totalHits' => $totalHits,
  280.             'totalPages' => $totalPages,
  281.         ]);
  282.     }
  283.     return $this->createRestView($configuration$orders);
  284. }
  285.     // @TODO: indexActionForAlgolia Will be removed later
  286.     public function indexActionForAlgolia(Request $request): Response
  287.     {
  288.         error_log('indexAction called');
  289.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  290.         $this->isGrantedOr403($configurationResourceActions::INDEX);
  291.         // Collect all criteria from filters
  292.         $filters $request->query->get('criteria', []);
  293.         // error_log(print_r($filters, true)); // Log filters for debugging
  294.         // Initialize search query
  295.         $searchConditions = [];
  296.         // Ensure filters is an array and construct the search query
  297.         if (is_array($filters)) {
  298.             foreach ($filters as $field => $criteria) {
  299.                 if (is_array($criteria)) {
  300.                     if (isset($criteria['value']) && !empty($criteria['value'])) {
  301.                         if($field === "customer"){
  302.                             $searchConditions[] = '('.$field '.companyName:"' $criteria['value'] . '" OR ' .$field '.code:"' $criteria['value'] . '")';
  303.                         }elseif($field === "postCode"){
  304.                             $searchConditions[] = 'orderAddress.' $field ':"' $criteria['value'] . '"';
  305.                         }else{
  306.                             $searchConditions[] = $field ':"' $criteria['value'] . '"';
  307.                         }
  308.                     } elseif ($field === 'date') {
  309.                         // Initialize variables for 'from' and 'to' timestamps
  310.                         $fromDateTime null;
  311.                         $toDateTime null;
  312.                         // Handle the 'from' part
  313.                         if (!empty($criteria['from']['date']) && !empty($criteria['from']['time'])) {
  314.                             // Both date and time provided
  315.                             $fromDateTime $criteria['from']['date'] . ' ' $criteria['from']['time'] . '.000000';
  316.                         } elseif (!empty($criteria['from']['date'])) {
  317.                             // Only date provided (set time to start of the day)
  318.                             $fromDateTime $criteria['from']['date'] . ' 00:00:00.000000';
  319.                         } elseif (!empty($criteria['from']['time'])) {
  320.                             // Only time provided (use current date with provided time)
  321.                             $fromDateTime date('Y-m-d') . ' ' $criteria['from']['time'] . '.000000';
  322.                         }
  323.                         // Handle the 'to' part
  324.                         if (!empty($criteria['to']['date']) && !empty($criteria['to']['time'])) {
  325.                             // Both date and time provided
  326.                             $toDateTime $criteria['to']['date'] . ' ' $criteria['to']['time'] . '.000000';
  327.                         } elseif (!empty($criteria['to']['date'])) {
  328.                             // Only date provided (set time to end of the day)
  329.                             $toDateTime $criteria['to']['date'] . ' 23:59:59.000000';
  330.                         } elseif (!empty($criteria['to']['time'])) {
  331.                             // Only time provided (use current date with provided time)
  332.                             $toDateTime date('Y-m-d') . ' ' $criteria['to']['time'] . '.000000';
  333.                         }
  334.                         // Convert the 'from' and 'to' date-time strings to Unix timestamps
  335.                         $fromTimestamp = !empty($fromDateTime) ? strtotime($fromDateTime) : null;
  336.                         $toTimestamp = !empty($toDateTime) ? strtotime($toDateTime) : null;
  337.                         // Construct the search condition if both timestamps are valid
  338.                         if ($fromTimestamp && $toTimestamp) {
  339.                             $searchConditions[] = 'createdAt.date: ' $fromTimestamp ' TO ' $toTimestamp;
  340.                         }
  341.                     }elseif ($field === 'amountExcludingTax' || $field === 'totalOrder') {
  342.                         if($field === 'totalOrder'){
  343.                             $field "netToPayAmount";
  344.                         }
  345.                         if (!empty($criteria['greaterThan'])) {
  346.                             $searchConditions[] = $field ' > ' . (float)$criteria['greaterThan']*100;
  347.                         }
  348.                         if (!empty($criteria['lessThan'])) {
  349.                             $searchConditions[] = $field ' < ' . (float)$criteria['lessThan']*100;
  350.                         }
  351.                         if (!empty($criteria['currency'])) {
  352.                             $searchConditions[] = 'currencyCode:' $criteria['currency'];
  353.                         }
  354.                     }elseif (!empty($criteria) && ($field == "orderType" || $field == "orderNature" || $field == "orderState" || $field == "shippingMethod" || $field == "city" )) {
  355.                         // Combine array values with logical OR using the correct format
  356.                         $conditions = [];
  357.                         foreach ($criteria as $value) {
  358.                             $conditions[] = $field '.id:' $value;
  359.                         }
  360.                         // Join the conditions with 'OR' and wrap them in parentheses
  361.                         $searchConditions[] = '(' implode(' OR '$conditions) . ')';
  362.                     }
  363.                 }else {
  364.                     if (!empty($criteria) && ($field == "orderType" || $field == "orderNature" || $field == "orderState" || $field == "shippingMethod" || $field == "city" )) {
  365.                         $searchConditions[] = $field '.id:"' $criteria '"';
  366.                     }
  367.                 }
  368.             }
  369.         }
  370.         // Concatenate search queries with AND operator
  371.         $searchQuery implode(' AND '$searchConditions);
  372.         // dd($searchQuery);
  373.         // Get search service from container
  374.         $searchService $this->container->get('search.client');
  375.         // Initialize Algolia index
  376.         $algoliaIndex $searchService->initIndex('orders_index');
  377.         $algoliaIndex->setSettings([
  378.             'attributesForFaceting' => [
  379.               "searchable(number)",
  380.               "searchable(object)",
  381.               "searchable(orderAddress)",
  382.               "searchable(depot)",
  383.               "searchable(entryDepot)",
  384.               "searchable(customer1)",
  385.               "searchable(customer2)",
  386.               "searchable(billingCustomer)",
  387.               "searchable(shippingCustomer)",
  388.               "searchable(shippingMethodCustomer)",
  389.               "searchable(orderType)",
  390.               "searchable(orderNature)",
  391.               "searchable(orderState)",
  392.               "searchable(customerPaymentMethod)",
  393.               "searchable(customerRepresentative)",
  394.               "searchable(shippingMethod)",
  395.               "searchable(shippingTaxRate)",
  396.               "searchable(taxRateGroup)",
  397.               "searchable(customer)",
  398.               "searchable(channel)",
  399.               "searchable(paymentDueDate)",
  400.               "searchable(text)",
  401.               "searchable(city)",
  402.               "searchable(amountExcludingTax)",
  403.               "searchable(amountExcludingDTax)",
  404.               "searchable(paidAmount)",
  405.               "searchable(taxAmount)",
  406.               "searchable(netToPayAmount)",
  407.               "searchable(commercialNetAmount)",
  408.               "searchable(financialNetAmount)",
  409.               "searchable(state)",
  410.               "searchable(createdAt)",
  411.               "searchable(updatedAt)",
  412.               "searchable(currencyCode)",
  413.             ]
  414.           ]);
  415.         $initialSearchResults $algoliaIndex->search('', [
  416.             'filters' => $searchQuery,
  417.             'hitsPerPage' => 0// Only fetch the count, no actual results needed
  418.         ]);
  419.         $totalAlgoliaHits $initialSearchResults['nbHits'];
  420.         error_log('Total Hits: ' $totalAlgoliaHits);
  421.         $algoliaIndex->setSettings([
  422.             'paginationLimitedTo' => $totalAlgoliaHits
  423.         ]);
  424.         // Perform search with pagination and filters
  425.         $page $request->query->get('page'1);
  426.         $limit $request->query->get('limit'50);
  427.         $hitsPerPage $limit// Define the number of results per page
  428.         // Set $limitPages based on $page
  429.         $coef = (int) ceil(999 $hitsPerPage);
  430.         if ($page $coef) {
  431.             $limitPages 0;
  432.         } else {
  433.             $limitPages floor($page $coef);
  434.         }
  435.         // Fetch results for pages 0, 1, and 2
  436.         $allResults = [];
  437.         for ($i 0$i <= $limitPages$i++) {
  438.             $searchResults $algoliaIndex->search('', [
  439.                 'filters' => $searchQuery,
  440.                 'page' => $i// Fetching up to the current page
  441.                 'hitsPerPage' => 999,
  442.             ]);
  443.             $allResults array_merge($allResults$searchResults['hits']);
  444.         }
  445.         // Capture total hits for proper pagination
  446.         $totalHits =  count($allResults);
  447.         $searchResults['hits'] = $allResults;
  448.         // Convert search results to array of Order entities
  449.         $orders = [];
  450.         foreach ($searchResults['hits'] as $hit) {
  451.             $order = new Order();
  452.             $order->setId((int)$hit['id']);  // Convert string to integer
  453.             $order->setNumber($hit['number']);
  454.             if (isset($hit['depot']) && $hit['depot'] !== null) {
  455.                 $order->setDepot($hit['depot']);
  456.             }
  457.             if (isset($hit['object']) && $hit['object'] !== null) {
  458.                 $order->setObject($hit['object']);
  459.             }
  460.             if (isset($hit['orderAddress']) && $hit['orderAddress'] !== null) {
  461.                 $order->setOrderAddress($hit['orderAddress']);
  462.             }
  463.             if (isset($hit['entryDepot']) && $hit['entryDepot'] !== null) {
  464.                 $order->setEntryDepot($hit['entryDepot']);
  465.             }
  466.             if (isset($hit['customer']) && $hit['customer'] !== null) {
  467.                 // Assuming Customer is your implementation of CustomerInterface
  468.                 $customer = new Customer(); // or any class that implements CustomerInterface
  469.                 // Set the fields on the customer object
  470.                 $customer->setId((int)$hit['customer']['id']);
  471.                 $customer->setCompanyName($hit['customer']['companyName']);
  472.                 $customer->setCode($hit['customer']['code']);
  473.                 // Now set the customer object on the order
  474.                 $order->setCustomer($customer);
  475.             }
  476.             if (isset($hit['customer1']) && $hit['customer1'] !== null) {
  477.                 $order->setCustomer1($hit['customer1']);
  478.             }
  479.             if (isset($hit['customer2']) && $hit['customer2'] !== null) {
  480.                 $order->setCustomer2($hit['customer2']);
  481.             }
  482.             if (isset($hit['billingCustomer']) && $hit['billingCustomer'] !== null) {
  483.                 $order->setBillingCustomer($hit['billingCustomer']);
  484.             }
  485.             if (isset($hit['shippingCustomer']) && $hit['shippingCustomer'] !== null) {
  486.                 $order->setShippingCustomer($hit['shippingCustomer']);
  487.             }
  488.             if (isset($hit['shippingMethodCustomer']) && $hit['shippingMethodCustomer'] !== null) {
  489.                 $order->setShippingMethodCustomer($hit['shippingMethodCustomer']);
  490.             }
  491.             if (isset($hit['orderNature']) && $hit['orderNature'] !== null) {
  492.                 $order->setOrderNature($hit['orderNature']);
  493.             }
  494.             if (isset($hit['orderType']) && $hit['orderType'] !== null) {
  495.                 $order->setOrderType($hit['orderType']);
  496.             }
  497.             if (isset($hit['customerPaymentMethod']) && $hit['customerPaymentMethod'] !== null) {
  498.                 $order->setCustomerPaymentMethod($hit['customerPaymentMethod']);
  499.             }
  500.             if (isset($hit['city']) && $hit['city'] !== null) {
  501.                 $order->setCity($hit['city']);
  502.             }
  503.             if (isset($hit['paymentMethod']) && $hit['paymentMethod'] !== null) {
  504.                 $order->setPaymentMethod($hit['paymentMethod']);
  505.             }
  506.             if (isset($hit['customerRepresentative']) && $hit['customerRepresentative'] !== null) {
  507.                 $order->setCustomerRepresentative($hit['customerRepresentative']);
  508.             }
  509.             if (isset($hit['text']) && $hit['text'] !== null) {
  510.                 $order->setText($hit['text']);
  511.             }
  512.             if (isset($hit['shippingMethod']) && $hit['shippingMethod'] !== null) {
  513.                 $order->setShippingMethod($hit['shippingMethod']);
  514.             }
  515.             if (isset($hit['shippingTaxRate']) && $hit['shippingTaxRate'] !== null) {
  516.                 $order->setShippingTaxRate((float) $hit['shippingTaxRate']);  // Cast to float if necessary
  517.             }
  518.             if (isset($hit['taxApplied']) && $hit['taxApplied'] !== null) {
  519.                 $order->setTaxApplied((bool) $hit['taxApplied']);  // Cast to boolean
  520.             }
  521.             if (isset($hit['status']) && $hit['status'] !== null) {
  522.                 $order->setStatus($hit['status']);
  523.             }
  524.             if (isset($hit['object']) && $hit['object'] !== null) {
  525.                 $order->setObject($hit['object']);
  526.             }
  527.             if (isset($hit['weight']) && $hit['weight'] !== null) {
  528.                 $order->setWeight((float) $hit['weight']);
  529.             }
  530.             if (isset($hit['orderState']) && $hit['orderState'] !== null) {
  531.                 $order->setOrderState($hit['orderState']);
  532.             }
  533.             if (isset($hit['attentionOf']) && $hit['attentionOf'] !== null) {
  534.                 $order->setAttentionOf($hit['attentionOf']);
  535.             }
  536.             if (isset($hit['loyaltyCheck']) && $hit['loyaltyCheck'] !== null) {
  537.                 $order->setLoyaltyCheck((bool) $hit['loyaltyCheck']);
  538.             }
  539.             if (isset($hit['mailingCode']) && $hit['mailingCode'] !== null) {
  540.                 $order->setMailingCode($hit['mailingCode']);
  541.             }
  542.             if (isset($hit['currencyCode']) && $hit['currencyCode'] !== null) {
  543.                 $order->setCurrencyCode($hit['currencyCode']);
  544.             }
  545.             if (isset($hit['amountExcludingTax']) && $hit['amountExcludingTax'] !== null) {
  546.                 $order->setAmountExcludingTax($hit['amountExcludingTax']/100);
  547.             }
  548.             if (isset($hit['netToPayAmount']) && $hit['netToPayAmount'] !== null) {
  549.                 $order->setNetToPayAmount($hit['netToPayAmount']/100);
  550.             }
  551.             if (isset($hit['createdAt']) && $hit['createdAt'] !== null) {
  552.                 $createdAt = (new \DateTime())->setTimestamp($hit['createdAt']['date']);
  553.                 $order->setCreatedAt($createdAt);
  554.             }
  555.             $orders[] = $order;
  556.         }
  557.         // Create Pagerfanta object for pagination
  558.         $adapter = new ArrayAdapter($orders);
  559.         $pagerfanta = new Pagerfanta($adapter);
  560.         $pagerfanta->setMaxPerPage($hitsPerPage);  // Set items per page
  561.         $pagerfanta->setCurrentPage($page);  // Handle page query param
  562.         // Calculate total pages
  563.         $totalPages ceil($totalHits $hitsPerPage);
  564.         if($searchResults['hits'] !== []){
  565.             $pagerfanta->setMaxNbPages((int)$totalPages);
  566.         }
  567.         // Get grid definition from the configuration
  568.         $gridDefinition $this->container->get('sylius.grid.provider')->get('sylius_admin_order');
  569.         // Create ResourceGridView object
  570.         $resourceGridView = new ResourceGridView(
  571.             $pagerfanta,
  572.             $gridDefinition,
  573.             new Parameters($request->query->all()),
  574.             $this->metadata,
  575.             $configuration
  576.         );
  577.         $this->eventDispatcher->dispatchMultiple(ResourceActions::INDEX$configuration$orders);
  578.         error_log('totalHits: '.$totalHits);
  579.         error_log('totalPages: '.$totalPages);
  580.         if ($configuration->isHtmlRequest()) {
  581.             return $this->render($configuration->getTemplate(ResourceActions::INDEX '.html'), [
  582.                 'configuration' => $configuration,
  583.                 'metadata' => $this->metadata,
  584.                 'resources' => $resourceGridView,
  585.                 'searchResults' => $searchResults,
  586.                 $this->metadata->getPluralName() => $resourceGridView,
  587.                 'totalHits' => $totalHits,  // Include total hits for reference
  588.                 'totalPages' => $totalPages// Total pages for pagination
  589.             ]);
  590.         }
  591.         return $this->createRestView($configuration$orders);
  592.     }
  593.     public function showAction(Request $request): Response
  594.     {
  595.         $isPaymentMethodAvailable = [];
  596.         $orderItemStates = [];
  597.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  598.         $this->isGrantedOr403($configurationResourceActions::SHOW);
  599.         /** @var Order $resource */
  600.         $resource $this->findOr404($configuration);
  601.         $this->eventDispatcher->dispatch(ResourceActions::SHOW$configuration$resource);
  602.         foreach ($resource->getPayments() as $payment) {
  603.             $isPaymentMethodAvailable[] = [
  604.                 'paymentId' => $payment->getId(),
  605.                 'isAvailable' => $this->repository->ifOrderHasPaymentMethod($resource->getLastPayment()->getId())
  606.             ];
  607.         }
  608.         // Load order items from FTP if applicable
  609.         // if ($resource->getLoadsFromFtp()) {
  610.          if (== 1) {
  611.             $this->ftpLogService $this->container->get('app.service.ftp_log_service');
  612.             $orderFtp $this->ftpLogService->getOrderLogs('flash_stock'$resource->getId());
  613.             if(count($orderFtp)==0){
  614.                 $orderFtp $this->ftpLogService->getOrderLogs('mvt_stock'$resource->getId());
  615.             }
  616.             if (!empty($orderFtp[0]['content'][0]['data'])) {
  617.                 $dataOrder $orderFtp[0]['content'][0]['data'];
  618.                 $entityManager $this->container->get('doctrine')->getManager();
  619.                 // Optional: Clear existing items
  620.                 foreach ($resource->getItems() as $item) {
  621.                     $resource->removeItem($item);
  622.                 }
  623.                 // Populate items
  624.                 foreach ($dataOrder["items"] as $itemData) {
  625.                     // create object orderItem and add it to $resource items without using function
  626.                     $orderItem = new OrderItem();
  627.                     if (!empty($itemData['product_id'])) {
  628.                         $variant $entityManager->getRepository(ProductVariantInterface::class)
  629.                             ->find($itemData['product_id']);
  630.                         if ($variant) {
  631.                             if($variant->getProduct()->getBarcode() == 0){
  632.                                 continue;
  633.                             }
  634.                             $orderItem->setVariant($variant);
  635.                         }
  636.                     }
  637.                     $orderItem->setQuantity((int)($itemData['new_stock'] ?? 1));
  638.                     $orderItem->setDesignation($itemData['designation'] ?? null);
  639.                     $orderItem->setReference($itemData['reference'] ?? null);
  640.                     $orderItem->setChecked((bool)($itemData['checked'] ?? false));
  641.                     $orderItem->setAccountingCode($itemData['accounting_code'] ?? null);
  642.                     $orderItem->setAnalyticalAccountingCode($itemData['analytical_accounting_code'] ?? null);
  643.                     $orderItem->setSupplyCoefficient($itemData['supply_coefficient'] ?? null);
  644.                     $orderItem->setCom((bool)($itemData['com'] ?? false));
  645.                     $orderItem->setComment($itemData['comment'] ?? null);
  646.                     $orderItem->setIsBold((bool)($itemData['is_bold'] ?? false));
  647.                     $orderItem->setIsItalic((bool)($itemData['is_italic'] ?? false));
  648.                     $orderItem->setMargin($itemData['margin'] ?? null);
  649.                     $orderItem->setMask((bool)($itemData['mask'] ?? false));
  650.                     $orderItem->setGrossAmount($itemData['ht_price'] ? $itemData['ht_price'] * (int)($itemData['new_stock']) : null);
  651.                     $orderItem->setNetPrice($itemData['ttc_price'] ?? null);
  652.                     $orderItem->setPrice($itemData['unit_price'] ?? null);
  653.                     $orderItem->setReturnPrice($itemData['return_price'] ?? null);
  654.                     $orderItem->setNumber($itemData['number'] ?? null);
  655.                     $orderItem->setWeight($itemData['weight'] ?? null);
  656.                     $orderItem->setPackagingQuantity($itemData['packaging_quantity'] ?? null);
  657.                     $orderItem->setPrintingQuantity($itemData['printing_quantity'] ?? null);
  658.                     $orderItem->setDiscountRate($itemData['discount_rate'] ?? null);
  659.                     $orderItem->setSecondDiscountRate($itemData['second_discount_rate'] ?? null);
  660.                     $orderItem->setSubItem((bool)($itemData['sub_item'] ?? false));
  661.                     $orderItem->setLockValue($itemData['lock_value'] ?? null);
  662.                     $orderItem->setState($itemData['state'] ?? null);
  663.                     $orderItem->setAvailabilityPercentage($itemData['availability_percentage'] ?? null);
  664.                     if (!empty($itemData['created_at'])) {
  665.                         $orderItem->setCreatedAt(new \DateTime($itemData['created_at']));
  666.                     }
  667.                     if (!empty($itemData['updated_at'])) {
  668.                         $orderItem->setUpdatedAt(new \DateTime($itemData['updated_at']));
  669.                     }
  670.                     if (!empty($itemData['taxRate_id'])) {
  671.                         $taxRate $entityManager
  672.                             ->getRepository(TaxRate::class)
  673.                             ->findOneBy(['id' => $itemData['taxRate_id']]);
  674.                         if ($taxRate) {
  675.                             $orderItem->setTaxRate($taxRate);
  676.                         }
  677.                     }
  678.                     // Add item to order
  679.                     $resource->addItem($orderItem);
  680.                 }
  681.                 // Optionally persist if you want to save it in DB (maybe not in a showAction?)
  682.                 //$this->entityManager->flush();
  683.                 // Debug output
  684.                 // dd('Load items from FTP');
  685.             }
  686.         }
  687.         foreach ($resource->getItems() as $item) {
  688.             $itemState $this->repository->fetchOrderItemState($item->getId());
  689.             $orderItemStates [] = [
  690.                 'id' => $item->getId(),
  691.                 'state' => $itemState
  692.             ];
  693.         }
  694.         if ($configuration->isHtmlRequest()) {
  695.             return $this->render($configuration->getTemplate(ResourceActions::SHOW '.html'), [
  696.                 'configuration' => $configuration,
  697.                 'metadata' => $this->metadata,
  698.                 'resource' => $resource,
  699.                 $this->metadata->getName() => $resource,
  700.                 'isPaymentMethodAvailable' => $isPaymentMethodAvailable,
  701.                 'orderItemStates' => $orderItemStates,
  702.                 'dates' => [
  703.                     'createdAt' => $this->repository->getOrderDateByState($resource->getId(), "En cours"),
  704.                     'preparedAt' => $this->repository->getOrderDateByState($resource->getId(), "En préparation"),
  705.                     'sentAt' => $this->repository->getOrderDateByState($resource->getId(), "expédiée"),
  706.                     'validatedAt' => $this->repository->getOrderDateByState($resource->getId(), "comptabilisée"),
  707.                 ]
  708.             ]);
  709.         }
  710.         return $this->createRestView($configuration$resource);
  711.     }
  712.     public function getTreeAction(Request $request): Response
  713.     {
  714.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  715.         $this->isGrantedOr403($configurationResourceActions::INDEX);
  716.         $resources $this->resourcesCollectionProvider->get($configuration$this->repository);
  717.         $this->eventDispatcher->dispatchMultiple(ResourceActions::INDEX$configuration$resources);
  718.         if ($configuration->isHtmlRequest()) {
  719.             return $this->render($configuration->getTemplate(ResourceActions::INDEX '.html'), [
  720.                 'configuration' => $configuration,
  721.                 'metadata' => $this->metadata,
  722.                 'resources' => $resources,
  723.                 $this->metadata->getPluralName() => $resources,
  724.             ]);
  725.         }
  726.         return $this->createRestView($configuration$resources);
  727.     }
  728.     public function editAction(Request $request$idIriConverterInterface $iriConverter): Response
  729.     {
  730.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  731.         $this->isGrantedOr403($configurationResourceActions::SHOW);
  732.         /** @var Order $order */
  733.         $order $this->findOr404($configuration);
  734.         // Adjust prices for order items only if the form is not submitted
  735.         if (!$request->isMethod('POST')) {
  736.             foreach ($order->getItems() as $item) {
  737.                 if ($item->getPrice() > && $item->getNetPrice() > 0) {
  738.                     $item->setPrice($item->getPrice() / 10000);
  739.                     $item->setNetPrice($item->getNetPrice() / 10000);
  740.                 }
  741.             }
  742.         }
  743.         $form $this->createForm(TypeOrder::class, $order);
  744.         $form->handleRequest($request);
  745.         if ($form->isSubmitted()) {
  746.             if (!$form->isValid()) {
  747.                 // More detailed error handling
  748.                 $errors = [];
  749.                 foreach ($form->getErrors(true) as $error) {
  750.                     $errors[] = $error->getMessage();
  751.                 }
  752.                 // Return form with errors
  753.                 return $this->render('@SyliusAdmin/Order/Crud/edit.html.twig', [
  754.                     'order' => $order,
  755.                     'form' => $form->createView(),
  756.                     'form_errors' => $errors
  757.                 ]);
  758.             }
  759.             try {
  760.                 if ($form->isSubmitted() && $form->isValid()) {
  761.                     $data $form->getData();
  762.                     //dd($data);
  763.                 }
  764.                 $entityManager $this->container->get('doctrine')->getManager();
  765.                 error_log('[DEBUG ORDER EDIT] Start processing order ' $order->getId() . ' at ' date('H:i:s'));
  766.                 
  767.                 $this->orderService $this->container->get(OrderService::class);
  768.                 
  769.                 error_log('[DEBUG ORDER EDIT] Before handleOrderItemsUpdate at ' date('H:i:s'));
  770.                 $this->orderService->handleOrderItemsUpdate($order);
  771.                 error_log('[DEBUG ORDER EDIT] After handleOrderItemsUpdate at ' date('H:i:s'));
  772.                 
  773.                 error_log('[DEBUG ORDER EDIT] Before fixItemsPrice at ' date('H:i:s'));
  774.                 $this->orderService->fixItemsPrice($order);
  775.                 error_log('[DEBUG ORDER EDIT] After fixItemsPrice at ' date('H:i:s'));
  776.                 // Persist the existing order with its updated data
  777.                 error_log('[DEBUG ORDER EDIT] Before persist/flush at ' date('H:i:s'));
  778.                 $entityManager->persist($order);
  779.                 $entityManager->flush();
  780.                 error_log('[DEBUG ORDER EDIT] After flush at ' date('H:i:s'));
  781.                 $this->addFlash('success''Commande modifié avec succès');
  782.                 return $this->redirectToRoute('app_admin_order_edit', ['id' => $order->getId()]);
  783.             } catch (\Exception $e) {
  784.                 error_log('[DEBUG ORDER EDIT] Exception: ' $e->getMessage());
  785.                 $this->addFlash('error''Erreur lors de la modification de la commande: ' $e->getMessage());
  786.             }
  787.         }
  788.         return $this->render('@SyliusAdmin/Order/Crud/edit.html.twig', [
  789.             'order' => $order,
  790.             'form' => $form->createView(),
  791.         ]);
  792.     }
  793.     public function editNFAction(Request $request$idIriConverterInterface $iriConverter): Response
  794.     {
  795.         $orderItemStates  = [];
  796.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  797.         $this->isGrantedOr403($configurationResourceActions::SHOW);
  798.         /** @var Order $order */
  799.         $order $this->findOr404($configuration);
  800.         if($order instanceof Order) {
  801.             foreach ($order->getItems() as $item) {
  802.                 if($item->getVariant()->getCode() != "Article_DEFAULT") {
  803.                     $itemState $this->repository->fetchOrderItemState($item->getId(), true);
  804.                     $orderItemStates [] = [
  805.                         'id' => $item->getId(),
  806.                         'label' => $itemState['label'],
  807.                         'value' => $itemState['value']
  808.                     ];
  809.                 }
  810.             }
  811.         }
  812.         // Adjust prices for order items only if the form is not submitted
  813.         if (!$request->isMethod('POST')) {
  814.             foreach ($order->getItems() as $item) {
  815.                 if ($item->getPrice() > && $item->getNetPrice() > 0) {
  816.                     $item->setPrice($item->getPrice() / 10000);
  817.                     $item->setNetPrice($item->getNetPrice() / 10000);
  818.                 }
  819.             }
  820.         }
  821.         $form $this->createForm(TypeOrder::class, $order, [
  822.             /*'attr' => [
  823.                 'order_item_states' => json_encode($orderItemStates), // Pass as JSON
  824.             ],*/
  825.         ]);
  826.         $form->handleRequest($request);
  827.         if ($form->isSubmitted()) {
  828.             if (!$form->isValid()) {
  829.                 // More detailed error handling
  830.                 $errors = [];
  831.                 foreach ($form->getErrors(true) as $error) {
  832.                     $errors[] = $error->getMessage();
  833.                 }
  834.                 // Return form with errors
  835.                 return $this->render('@SyliusAdmin/Order/Crud/edit_nf.html.twig', [
  836.                     'order' => $order,
  837.                     'orderItemStates' => $orderItemStates,
  838.                     'form' => $form->createView(),
  839.                     'form_errors' => $errors
  840.                 ]);
  841.             }
  842.             $this->orderService $this->container->get(OrderService::class);
  843.             try {
  844.                 if ($form->isSubmitted() && $form->isValid()) {
  845.                     $order $form->getData();
  846.                 }
  847.                 $entityManager $this->container->get('doctrine')->getManager();
  848.                 //TODO: handle the change of items state
  849.                 foreach ($order->getItems() as $item) {
  850.                     $this->handleItemStatus($item);
  851.                 }
  852.                 $this->orderService->fixItemsPrice($order);
  853.                 // Persist the existing order with its updated data
  854.                 $entityManager->persist($order);
  855.                 $entityManager->flush();
  856.                 $this->addFlash('success''Commande modifiée avec succès');
  857.                 return $this->redirectToRoute('app_admin_nf_order_edit', ['id' => $order->getId()]);
  858.             } catch (\Exception $e) {
  859.                 $this->addFlash('error''Erreur lors de la modification de la commande: ' $e->getMessage());
  860.             }
  861.         }
  862.         return $this->render('@SyliusAdmin/Order/Crud/edit_nf.html.twig', [
  863.             'order' => $order,
  864.             'orderItemStates' => $orderItemStates,
  865.             'form' => $form->createView(),
  866.         ]);
  867.     }
  868.     public function handleItemStatus(OrderItem $item) {
  869.         $oldStatus $this->repository->fetchOrderItemState($itemtrue)['value'];
  870.         $this->removeOldState($item->getId(), $oldStatus);
  871.         $newItem null;
  872.         switch ($item->getState()) {
  873.             case 1:
  874.                 $newItem = new OrderItemRequirement();
  875.                 break;
  876.             case 2:
  877.                 $newItem = new OrderItemReservation();
  878.                 break;
  879.             case -1:
  880.                 $newItem = new OrderItemCancellation();
  881.                 break;
  882.         }
  883.         if($newItem) {
  884.             $this->createNewItemStatus($item$newItem);
  885.         }
  886.         $this->manager->flush();
  887.     }
  888.     public function createNewItemStatus(OrderItem $item$newItem) {
  889.         $newItem->setOrderItem($item);
  890.         $newItem->setQuantity($item->getQuantity());
  891.         if($newItem instanceof OrderItemRequirement) {
  892.             $newItem->setRequiredAt(new \DateTime());
  893.             $newItem->setUpdatedAt(new \DateTime());
  894.         }
  895.         if($newItem instanceof OrderItemReservation) {
  896.             $newItem->setReservedAt(new \DateTime());
  897.         }
  898.         if($newItem instanceof OrderItemCancellation) {
  899.             $newItem->setCancelledAt(new \DateTime());
  900.         }
  901.         $this->manager->persist($newItem);
  902.     }
  903.     public function removeOldState($itemId$oldStatus) {
  904.         $itemToRemove null;
  905.         switch ($oldStatus) {
  906.             case 1:
  907.                 $itemToRemove $this->manager->getRepository(OrderItemRequirement::class)->findBy(['orderItem' => $itemId]);
  908.                 break;
  909.             case 2:
  910.                 $itemToRemove $this->manager->getRepository(OrderItemReservation::class)->findBy(['orderItem' => $itemId]);
  911.                 break;
  912.             case -1:
  913.                 $itemToRemove $this->manager->getRepository(OrderItemCancellation::class)->findBy(['orderItem' => $itemId]);
  914.                 break;
  915.         }
  916.         if($itemToRemove) {
  917.             foreach ($itemToRemove as $item) {
  918.                 $this->manager->remove($item);
  919.             }
  920.         }
  921.     }
  922.     public function addAction(Request $request): Response
  923.     {
  924.         // Create a new Order instance
  925.         $order = new Order();
  926.         $defaultDepot $this->container->get('doctrine')
  927.             ->getRepository(Depot::class)
  928.             ->find(1);
  929.         $defaultOrderType $this->container->get('doctrine')
  930.             ->getRepository(OrderType::class)
  931.             ->find(3);
  932.         $order->setDepot($defaultDepot);
  933.         $order->setOrderType($defaultOrderType);
  934.         // Create the form for the new order
  935.         $form $this->createForm(TypeOrder::class, $order);
  936.         $form->handleRequest($request);
  937.         if ($form->isSubmitted()) {
  938.             if (!$form->isValid()) {
  939.                 // Gather errors if form validation fails
  940.                 $errors = [];
  941.                 foreach ($form->getErrors(true) as $error) {
  942.                     $errors[] = $error->getMessage();
  943.                 }
  944.                 // Return the form with errors for user feedback
  945.                 return $this->render('@SyliusAdmin/Order/Crud/add.html.twig', [
  946.                     'order' => $order,
  947.                     'form' => $form->createView(),
  948.                     'form_errors' => $errors
  949.                 ]);
  950.             }
  951.             try {
  952.                 //TODO: update text generation code
  953.                 $entityManager $this->container->get('doctrine')->getManager();
  954.                 // Generating the order's number TODO: update text generation code
  955.                 /*$orderType = $order->getOrderType();
  956.                 $lastInvoiceNumber = $orderType->getCounter();
  957.                 $newInvoiceNumber = $lastInvoiceNumber + 1;
  958.                 $order->setText($newInvoiceNumber);
  959.                 $orderType->setCounter($newInvoiceNumber);*/
  960.                 $order->setCurrencyCode(("EUR"));
  961.                 $order->setLocaleCode("fr_FR");
  962.                 $order->setState("new");
  963.                 $this->orderService $this->container->get(OrderService::class);
  964.                 $this->orderService->generateInvoiceNumber($order);
  965.                 if($order->getOrderNature() && $order->getOrderNature()->getId() == 83) {
  966.                     $this->orderService->generateExOrder($order);
  967.                 } else {
  968.                     $this->orderService->handleMultiVat($order);
  969.                 }
  970.                 if($order->getOrderType() && $order->getOrderType()->getId() == 23) {
  971.                     $order->setWasProforma(true);
  972.                 }
  973.                 $this->orderService->fixItemsPrice($order);
  974.                 // Persist the new order and orderType after update
  975.                 $entityManager->persist($order);
  976.                 //$entityManager->persist($orderType);
  977.                 $entityManager->flush();
  978.                 // Add a success flash message
  979.                 $this->addFlash('success''Nouvelle commande ajoutée avec succès');
  980.                 return $this->redirectToRoute('app_admin_order_edit', ['id' => $order->getId()]);
  981.             } catch (\Exception $e) {
  982.                 /*$requestData = $request->request->all();
  983.                 dd([
  984.                     'error' => $e->getMessage(),
  985.                     'items_data' => $requestData['order']['items'] ?? null,
  986.                     'items_count' => count($requestData['order']['items'] ?? []),
  987.                     'first_item' => isset($requestData['order']['items'][0]) ? $requestData['order']['items'][0] : null,
  988.                 ]);*/
  989.                 $this->addFlash('error''Erreur lors de la modification de la commande: ' $e->getMessage());
  990.             }
  991.         }
  992.         // Render the form for adding a new order
  993.         return $this->render('@SyliusAdmin/Order/Crud/add.html.twig', [
  994.             'order' => $order,
  995.             'form' => $form->createView(),
  996.         ]);
  997.     }
  998.     public function deleteOrderAction(Request $request$id): Response
  999.     {
  1000.         $configuration $this->requestConfigurationFactory->create($this->metadata$request);
  1001.         $this->isGrantedOr403($configurationResourceActions::DELETE);
  1002.         /** @var Order $order */
  1003.         $order $this->findOr404($configuration);
  1004.         try {
  1005.             $entityManager $this->container->get('doctrine')->getManager();
  1006.             // Remove the order
  1007.             $entityManager->remove($order);
  1008.             $entityManager->flush();
  1009.             // Add a success flash message
  1010.             $this->addFlash('success''Commande supprimée avec succès');
  1011.         } catch (\Exception $e) {
  1012.             // Add an error flash message if something goes wrong
  1013.             $this->addFlash('error''Erreur lors de la suppression de la commande: ' $e->getMessage());
  1014.         }
  1015.         // Redirect back to the order list or another appropriate page
  1016.         return $this->redirectToRoute('app_admin_order_index');
  1017.     }
  1018.     public function processOrderFeedbackAction(Request $request) {
  1019.         //TODO: verify first if there is a file
  1020.         $this->orderService $this->container->get(OrderService::class);
  1021.         $ifFileExists $this->orderService->verifyOrderFeedbackFiles();
  1022.         /*if(!$ifFileExists) {
  1023.             $this->addFlash('error', "Aucun nouveau CR trouvé");
  1024.             return $this->redirectToRoute('sylius_admin_order_index');
  1025.         }*/
  1026.         $kernel $this->container->get('kernel');
  1027.         $command sprintf('php %s/bin/console %s'$kernel->getProjectDir(), 'app:process-orders-launch-feedback');
  1028.         exec("$command > /dev/null 2>&1 &");
  1029.         $this->addFlash('success'"Le processus récupération de préparation des commandes a été lancé avec succès");
  1030.         return $this->redirectToRoute('sylius_admin_order_index');
  1031.     }
  1032.     public function getNatureByOrderType(int $id): JsonResponse {
  1033.         $natures $this->container->get('doctrine')->getRepository(OrderNature::class)->findBy(['orderType' => $id]);
  1034.         if(!$natures){
  1035.            $natures $this->container->get('doctrine')->getRepository(OrderNature::class)->findBy(['orderType' => 3]);
  1036.         }
  1037.         $naturesArray = [];
  1038.         foreach ($natures as $nature) {
  1039.             $naturesArray [] = ['id' => $nature->getId(), 'name' => $nature->getName(), 'code' => $nature->getCode()];
  1040.         }
  1041.         return new JsonResponse($naturesArrayResponse::HTTP_OK);
  1042.     }
  1043.     public function getStateByOrderType(int $id): JsonResponse {
  1044.         $states $this->container->get('doctrine')->getRepository(OrderState::class)->findBy(['orderType' => $id]);
  1045.         $statesArray = [];
  1046.         foreach ($states as $state) {
  1047.             $statesArray [] = ['id' => $state->getId(), 'name' => $state->getName()];
  1048.         }
  1049.         return new JsonResponse($statesArrayResponse::HTTP_OK);
  1050.     }
  1051.     public function getStatusByOrderType(int $id): JsonResponse {
  1052.         $statusList $this->container->get('doctrine')->getRepository(Stat::class)->findBy(['orderType' => $id]);
  1053.         $statesArray = [];
  1054.         foreach ($statusList as $status) {
  1055.             $statesArray [] = ['id' => $status->getId(), 'name' => $status->getName()];
  1056.         }
  1057.         return new JsonResponse($statesArrayResponse::HTTP_OK);
  1058.     }
  1059.     public function getDueDateByCustomerPaymentMethod(int $id): JsonResponse {
  1060.         $this->orderService $this->container->get(OrderService::class);
  1061.         $dueDate $this->orderService->calculateDueDateByCustomerPaymentMethod($id);
  1062.         return new JsonResponse(['dueDate' => $dueDate], Response::HTTP_OK);
  1063.     }
  1064.     public function createFinancialInvoice(Request $request) {
  1065.         /*$this->orderService = $this->container->get(OrderService::class);
  1066.         $response = $this->orderService->createFinancialInvoice($request->files->get('csv_file'));
  1067.         $this->addFlash($response['type'], $response['message']);
  1068.         return $this->redirectToRoute('sylius_admin_order_index', ['id' => $response['id']]);*/
  1069.         /** @var UploadedFile|null $file */
  1070.         $file $request->files->get('csv_file');
  1071.         if (!$file) {
  1072.             $this->addFlash('error''No CSV file uploaded.');
  1073.             return $this->redirectToRoute('sylius_admin_order_index');
  1074.         }
  1075.         $kernel $this->container->get('kernel');
  1076.         $tempPath sys_get_temp_dir() . '/' uniqid('invoice_') . '.csv';
  1077.         $file->move(dirname($tempPath), basename($tempPath));
  1078.         $commandName sprintf(
  1079.             'app:create-financial-invoices --file=%s',
  1080.             escapeshellarg($tempPath)
  1081.         );
  1082.         $command sprintf('php %s/bin/console %s'$kernel->getProjectDir(), $commandName);
  1083.         exec("$command > /dev/null 2>&1 &");
  1084.         $this->addFlash('success''Import CSV lancé en arrière-plan.');
  1085.         return $this->redirectToRoute('sylius_admin_order_index');
  1086.     }
  1087.     public function createAmazonInvoices(Request $request) {
  1088.         /** @var UploadedFile|null $file */
  1089.         $file $request->files->get('csv_file');
  1090.         $customerId $request->get('customer_id');
  1091.         $orderTypeId $request->get('order_type_id');
  1092.         if (!$file) {
  1093.             $this->addFlash('error''No CSV file uploaded.');
  1094.             return $this->redirectToRoute('sylius_admin_order_index');
  1095.         }
  1096.         $kernel $this->container->get('kernel');
  1097.         $tempPath sys_get_temp_dir() . '/' uniqid('invoice_') . '.csv';
  1098.         $file->move(dirname($tempPath), basename($tempPath));
  1099.         $commandName sprintf(
  1100.             'app:create-amazon-invoices --file=%s --customerId=%d --orderTypeId=%d',
  1101.             escapeshellarg($tempPath),
  1102.             (int) $customerId,
  1103.             (int) $orderTypeId
  1104.         );
  1105.     $command sprintf('php %s/bin/console %s'$kernel->getProjectDir(), $commandName);
  1106.         exec("$command > /dev/null 2>&1 &");
  1107.         $this->addFlash('success''Import CSV lancé en arrière-plan.');
  1108.         return $this->redirectToRoute('sylius_admin_order_index');
  1109.     }
  1110.     public function analyseAmazonFile(Request $request) {
  1111.         /** @var UploadedFile|null $file */
  1112.         $file $request->files->get('csv_file');
  1113.         $customerId $request->get('customer_id');
  1114.         if (!$file) {
  1115.             $this->addFlash('error''No file uploaded.');
  1116.             return $this->redirectToRoute('sylius_admin_order_index');
  1117.         }
  1118.         $kernel $this->container->get('kernel');
  1119.         $extension $file->getClientOriginalExtension() ?: 'tmp';
  1120.         $filename uniqid('amazon_file_') . '.' $extension;
  1121.         $tempPath '/var/www/erpdodcie/erpdodcie_api/var/tmp/' $filename;
  1122.         $file->move(dirname($tempPath), basename($tempPath));
  1123.         $commandName sprintf(
  1124.             'app:analyse-amazon-file --file=%s --customerId=%d',
  1125.             escapeshellarg($tempPath),
  1126.             (int) $customerId
  1127.         );
  1128.         $command sprintf('php %s/bin/console %s'$kernel->getProjectDir(), $commandName);
  1129.         exec("$command > /dev/null 2>&1 &");
  1130.         $this->addFlash('success''Import Amazon est lancé en arrière-plan');
  1131.         return $this->redirectToRoute('sylius_admin_order_index');
  1132.     }
  1133.     public function handlePriceChange(Request $request) {
  1134.         $kernel $this->container->get('kernel');
  1135.         $orderItems json_decode($request->request->get('ids'), true);
  1136.         //$barcode = $request->request->get('barcode');
  1137.         $commandName sprintf(
  1138.             'app:handle-price-change --orderItems=%s',
  1139.             escapeshellarg(json_encode($orderItems))
  1140.         );
  1141.         $command sprintf('php %s/bin/console %s'$kernel->getProjectDir(), $commandName);
  1142.         exec("$command > /dev/null 2>&1 &");
  1143.         $this->addFlash('success'"Le processus de changement du prix est lancé");
  1144.         return new JsonResponse([
  1145.             'status' => 'success',
  1146.             'clearStorage' => true,
  1147.         ]);
  1148.     }
  1149.     public function duplicateInvoice(int $id) {
  1150.         $this->orderService $this->container->get(OrderService::class);
  1151.         $newInvoiceId $this->orderService->duplicateInvoice($id);
  1152.         $this->addFlash('success'"La facture a été dupliquée avec succès");
  1153.         return $this->redirectToRoute('app_admin_order_edit', ['id' => $newInvoiceId]);
  1154.     }
  1155.     public function recalculateOrderAmount(int $id) {
  1156.         $this->orderService $this->container->get(OrderService::class);
  1157.         $this->orderService->recalculateOrderAmount($id);
  1158.         return new JsonResponse('SUCCESS'Response::HTTP_OK);
  1159.     }
  1160.     /*public function recalculateOrdersDataByDate(Request $request) {
  1161.         $this->orderService = $this->container->get(OrderService::class);
  1162.         $message = $this->orderService->recalculateOrdersDataByDate($request->request->all());
  1163.         return new JsonResponse($message['message'], $message['type'] == 1 ? Response::HTTP_OK : Response::HTTP_BAD_REQUEST);
  1164.     }*/
  1165.     public function generateAssetNumber(int $id) {
  1166.         $this->orderService $this->container->get(OrderService::class);
  1167.         $generateAssetNumber $this->orderService->generateAssetNumber($id);
  1168.         $this->addFlash($generateAssetNumber['type'], $generateAssetNumber['message']);
  1169.         return $this->redirectToRoute('app_admin_order_edit', ['id' => $id]);
  1170.     }
  1171.         public function deleteAvoir(int $id) {
  1172.  $em $this->getDoctrine()->getManager();
  1173. $order $em->getRepository(Order::class)->find($id);
  1174. if (!$order) {
  1175.     throw $this->createNotFoundException("Order $id not found");
  1176. }
  1177. $orderType $em->getRepository(OrderType::class)->find(22);
  1178. if (!$orderType) {
  1179.     throw $this->createNotFoundException("OrderType 22 not found");
  1180. }
  1181. $order->setOrderType($orderType);
  1182. $em->flush();
  1183.    $kernel $this->container->get('kernel');
  1184. $projectDir $kernel->getProjectDir();
  1185. $cmd sprintf(
  1186.     'nohup php %s/bin/console app:cleanup-returned-quantities %s --no-ansi --no-interaction >> %s/var/log/cleanup_%d.log 2>&1 & echo $!',
  1187.     escapeshellarg($projectDir),
  1188.     escapeshellarg((string)$id),
  1189.     escapeshellarg($projectDir),
  1190.     $id
  1191. );
  1192. $pid trim(shell_exec($cmd));
  1193. if (!ctype_digit($pid)) {
  1194.     $this->addFlash('danger'"Le lancement du cleanup a échoué pour #$id.");
  1195. } else {
  1196.     $this->addFlash('success'"Avoir(#$id), supprimé !");
  1197.     return $this->redirectToRoute("sylius_admin_order_index");
  1198. }
  1199.         }
  1200.     public function reversePurchaseTrace(Request $request) {
  1201.         $this->orderService $this->container->get(OrderService::class);
  1202.         $this->orderService->reversePurchaseTrace();
  1203.         return new JsonResponse('success'Response::HTTP_OK);
  1204.     }
  1205.     public function cancelItem(Request $request)  {
  1206.         /** @var OrderService orderService */
  1207.         $this->orderService $this->container->get(OrderService::class);
  1208.         $message $this->orderService->cancelItem($request->request->all());
  1209.         return new JsonResponse($message['message'], $message['code']);
  1210.     }
  1211.     public function getParentObjects(int $id){
  1212.         /** @var OrderService orderService */
  1213.         $this->orderService $this->container->get(OrderService::class);
  1214.         return new JsonResponse($this->orderService->getParentObjects($id), Response::HTTP_OK);
  1215.     }
  1216. }