src/Controller/EgdDeclarationController.php line 20

  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\EgdDeclaration;
  4. use App\Repository\EgdDeclarationRepository;
  5. use App\Service\Egd\EgdApiClient;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  8. use Symfony\Component\HttpFoundation\Request;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\Routing\Annotation\Route;
  11. #[Route('/egd-declaration')]
  12. class EgdDeclarationController extends AbstractController
  13. {
  14.     #[Route('/upload'name'app_egd_declaration_upload'methods: ['GET''POST'])]
  15.     public function uploadExcel(
  16.         Request $request
  17.         EntityManagerInterface $em
  18.         EgdApiClient $apiClient,
  19.         \App\Service\Egd\EgdXmlBuilder $xmlBuilder
  20.     ): Response {
  21.         if ($request->isMethod('POST')) {
  22.             $uploadedFile $request->files->get('file');
  23.             if ($uploadedFile) {
  24.                 try {
  25.                     $fileDirectory $this->getParameter('kernel.project_dir') . '/var/uploads';
  26.                     if (!is_dir($fileDirectory)) {
  27.                         mkdir($fileDirectory0777true);
  28.                     }
  29.                     $originalExtension pathinfo($uploadedFile->getClientOriginalName(), PATHINFO_EXTENSION);
  30.                     $newFilename uniqid() . '.' $originalExtension;
  31.                     
  32.                     $uploadedFile->move($fileDirectory$newFilename);
  33.                     $filePath $fileDirectory '/' $newFilename;
  34.                     if (!class_exists('\PhpOffice\PhpSpreadsheet\IOFactory')) {
  35.                         throw new \Exception('PhpSpreadsheet is not installed. Please run: composer require phpoffice/phpspreadsheet');
  36.                     }
  37.                     $spreadsheet \PhpOffice\PhpSpreadsheet\IOFactory::load($filePath);
  38.                     $worksheet $spreadsheet->getActiveSheet();
  39.                     
  40.                     $data = [];
  41.                     $columnHeaders = [];
  42.                     
  43.                     foreach ($worksheet->getRowIterator() as $row) {
  44.                         foreach ($row->getCellIterator() as $cell) {
  45.                             $columnHeaders[] = $cell->getValue();
  46.                         }
  47.                         break; 
  48.                     }
  49.                     foreach ($worksheet->getRowIterator() as $rowIndex => $row) {
  50.                         if ($rowIndex === 1) continue; // Skip headers
  51.                         
  52.                         $rowValues = [];
  53.                         $cellIterator $row->getCellIterator();
  54.                         $cellIterator->setIterateOnlyExistingCells(false);
  55.                         foreach ($cellIterator as $cell) {
  56.                             $rowValues[] = $cell->getValue();
  57.                         }
  58.                         // Make sure we have the same number of keys and values
  59.                         if (count($columnHeaders) === count($rowValues)) {
  60.                             $data[] = array_combine($columnHeaders$rowValues);
  61.                         }
  62.                     }
  63.                     // Build XML
  64.                     $masterWaybillId $request->request->get('masterWaybillId''TD-000000001');
  65.                     $xmlData $xmlBuilder->buildFromExcelData($data$masterWaybillId);
  66.                     // Create Local Declaration
  67.                     $declaration = new EgdDeclaration();
  68.                     $courierDocId $this->generateUuid();
  69.                     $messageId $this->generateUuid();
  70.                     
  71.                     $declaration->setCourierDocId($courierDocId);
  72.                     $declaration->setMessageId($messageId);
  73.                     $declaration->setMasterWaybillId($masterWaybillId);
  74.                     $declaration->setOperation('Store');
  75.                     $declaration->setStatus('PENDING_SUBMIT');
  76.                     $declaration->setXmlData($xmlData);
  77.                     
  78.                     $em->persist($declaration);
  79.                     $em->flush();
  80.                     // Submit to EGD API
  81.                     $response $apiClient->submitDeclaration($courierDocId$messageId'Store'$xmlData);
  82.                     
  83.                     if ($response['success']) {
  84.                         $declaration->setStatus('SUBMITTED');
  85.                         $this->addFlash('success''Excel processed and declaration successfully submitted to EGD.');
  86.                     } else {
  87.                         $declaration->setStatus('FAILED');
  88.                         $declaration->setErrors($response['error'] ?? null);
  89.                         $this->addFlash('error''Failed to submit declaration to EGD.');
  90.                     }
  91.                     
  92.                     $em->flush();
  93.                     // Cleanup temp file
  94.                     @unlink($filePath);
  95.                     return $this->redirectToRoute('app_egd_declaration_show', ['id' => $declaration->getId()]);
  96.                     
  97.                 } catch (\Exception $e) {
  98.                     $this->addFlash('error''Error processing Excel: ' $e->getMessage());
  99.                 }
  100.             } else {
  101.                 $this->addFlash('error''No file uploaded.');
  102.             }
  103.         }
  104.         return $this->render('egd_declaration/upload.html.twig');
  105.     }
  106.     #[Route('/new'name'app_egd_declaration_new'methods: ['GET''POST'])]
  107.     public function new(Request $requestEntityManagerInterface $emEgdApiClient $apiClient): Response
  108.     {
  109.         if ($request->isMethod('POST')) {
  110.             $xmlData $request->request->get('xmlData');
  111.             
  112.             if (empty($xmlData)) {
  113.                 $this->addFlash('error''XML Data cannot be empty.');
  114.                 return $this->redirectToRoute('app_egd_declaration_new');
  115.             }
  116.             $declaration = new EgdDeclaration();
  117.             $courierDocId $this->generateUuid();
  118.             $messageId $this->generateUuid();
  119.             
  120.             $declaration->setCourierDocId($courierDocId);
  121.             $declaration->setMessageId($messageId);
  122.             $declaration->setOperation('Store');
  123.             $declaration->setStatus('PENDING_SUBMIT');
  124.             $declaration->setXmlData($xmlData);
  125.             
  126.             $em->persist($declaration);
  127.             $em->flush();
  128.             // Submit to EGD
  129.             $response $apiClient->submitDeclaration($courierDocId$messageId'Store'$xmlData);
  130.             
  131.             if ($response['success']) {
  132.                 $declaration->setStatus('SUBMITTED');
  133.                 $this->addFlash('success''Declaration successfully submitted to EGD.');
  134.             } else {
  135.                 $declaration->setStatus('FAILED');
  136.                 $declaration->setErrors($response['error'] ?? null);
  137.                 $this->addFlash('error''Failed to submit declaration to EGD.');
  138.             }
  139.             
  140.             $em->flush();
  141.             return $this->redirectToRoute('app_egd_declaration_show', ['id' => $declaration->getId()]);
  142.         }
  143.         // We load the sample XML for convenience
  144.         $sampleXmlPath $this->getParameter('kernel.project_dir') . '/sample-DGEC-declaration.xml';
  145.         $sampleXml file_exists($sampleXmlPath) ? file_get_contents($sampleXmlPath) : '';
  146.         return $this->render('egd_declaration/new.html.twig', [
  147.             'sampleXml' => $sampleXml,
  148.         ]);
  149.     }
  150.     #[Route('/{id}'name'app_egd_declaration_show'methods: ['GET'])]
  151.     public function show(EgdDeclaration $declaration): Response
  152.     {
  153.         return $this->render('egd_declaration/show.html.twig', [
  154.             'declaration' => $declaration,
  155.         ]);
  156.     }
  157.     #[Route('/{id}/refresh'name'app_egd_declaration_refresh'methods: ['POST'])]
  158.     public function refresh(EgdDeclaration $declarationEgdApiClient $apiClientEntityManagerInterface $em): Response
  159.     {
  160.         $response $apiClient->getSubmissionStatus($declaration->getMessageId());
  161.         
  162.         if ($response['status'] === 200) {
  163.             $data $response['data'];
  164.             if (isset($data['status'])) {
  165.                 $declaration->setStatus($data['status']);
  166.                 $em->flush();
  167.                 $this->addFlash('success''Status refreshed from EGD.');
  168.             }
  169.         } else {
  170.             $this->addFlash('error''Could not refresh status. HTTP Code: ' $response['status']);
  171.         }
  172.         return $this->redirectToRoute('app_egd_declaration_show', ['id' => $declaration->getId()]);
  173.     }
  174.     private function generateUuid(): string
  175.     {
  176.         $data random_bytes(16);
  177.         $data[6] = chr(ord($data[6]) & 0x0f 0x40); 
  178.         $data[8] = chr(ord($data[8]) & 0x3f 0x80); 
  179.         return vsprintf('%s%s-%s-%s-%s-%s%s%s'str_split(bin2hex($data), 4));
  180.     }
  181. }