src/Controller/Customer/FormController.php line 49

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Customer;
  3. use App\Classes\Customer\OrderPostmanPersist;
  4. use App\Classes\Tools\FlexibeeConnector;
  5. use App\Entity\OrderPostman;
  6. use App\Exception\InvalidPriceException;
  7. use App\Repository\ConfigurationRepository;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  10. use Symfony\Component\Form\Form;
  11. use Symfony\Component\Form\FormInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\HttpFoundation\Session\Session;
  15. use Symfony\Component\Security\Csrf\CsrfToken;
  16. use Symfony\Contracts\Translation\TranslatorInterface;
  17. use App\Classes\Customer\QrPayment;
  18. use App\Classes\Tools\Mailer;
  19. use App\Classes\Tools\Tools;
  20. use App\Entity\CarrierPricePostman;
  21. use App\Entity\Configuration;
  22. use App\Entity\Country;
  23. use App\Entity\PackageCode;
  24. use App\Entity\Order;
  25. use App\Entity\PregeneratedCode;
  26. use App\Form\Customer\SimpleOrderType;
  27. use Psr\Log\LoggerInterface;
  28. use Exception;
  29. use Throwable;
  30. class FormController extends AbstractController
  31. {
  32.     /**
  33.      * Controller zobrazi homepage stranku custommer casti a resi odeslani formulare s objednavkou zakaznika
  34.      *
  35.      * @param EntityManagerInterface $em
  36.      * @param LoggerInterface $ordersLogger log channel orders
  37.      * @param Mailer $mailer
  38.      * @param Request $request
  39.      * @param TranslatorInterface $translator
  40.      * @param FlexibeeConnector $flexibeeConnector
  41.      * @param string|null $deliveryTo nepovinny parametr pro zemi doruceni
  42.      *
  43.      * @return Response
  44.      * @throws Exception
  45.      */
  46.     public function index(
  47.         EntityManagerInterface $em,
  48.         LoggerInterface $ordersLogger,
  49.         Mailer $mailer,
  50.         Request $request,
  51.         TranslatorInterface $translator,
  52.         FlexibeeConnector $flexibeeConnector,
  53.         ?string $deliveryTo
  54.     ): Response {
  55.         $config $em->getRepository(Configuration::class);
  56.         $session $request->getSession();
  57.         $defaultCountry $this->getDefaultDeliveryCountry($em$session$translator$deliveryTo);
  58.         //nacitani predgenerovanych kodu
  59.         $code $session->get('code');
  60.         if (is_null($code)) {
  61.             $code $this->getPregenCodeAndSetInSession($em$session$mailer);
  62.         }
  63.         //formular objednavky
  64.         $simpleOrderForm $this->createForm(
  65.             SimpleOrderType::class,
  66.             null,
  67.             [
  68.                 'entityManager' => $em,
  69.                 'deliveryCountry' => $defaultCountry->getIso()
  70.             ]
  71.         );
  72.         $simpleOrderForm->handleRequest($request);
  73.         if ($simpleOrderForm->isSubmitted() && $this->simpleOrderTypeValidation(
  74.             $simpleOrderForm,
  75.             $translator,
  76.             $ordersLogger
  77.         )) {
  78.             return $this->processSubmitedFormAndRedirect(
  79.                 $simpleOrderForm,
  80.                 $code,
  81.                 $session,
  82.                 $mailer,
  83.                 $config,
  84.                 $translator,
  85.                 $flexibeeConnector,
  86.                 $ordersLogger,
  87.                 $em
  88.             );
  89.         }
  90.         return $this->render(
  91.             'Customer/Postman/form.html.twig',
  92.             [
  93.                 'defaultCountry' => $defaultCountry,
  94.                 'code' => $code,
  95.                 'orderForm' => $simpleOrderForm->createView(),
  96.                 'depo_address_name' => $config->get('depo_address_name'),
  97.                 'depo_address_street' => $config->get('depo_address_street'),
  98.                 'depo_address_city' => $config->get('depo_address_city'),
  99.                 'depo_address_zipcode' => $config->get('depo_address_zipcode'),
  100.                 'support_postman_email' => $config->get('support_postman_email'),
  101.                 'support_postman_phone' => $config->get('support_postman_phone')
  102.             ]
  103.         );
  104.     }
  105.     /**
  106.      * Zobrazi dekovnou stranku s udaji o platbe
  107.      *
  108.      * @param EntityManagerInterface $em
  109.      * @param Request $request
  110.      * @param QrPayment $qrPayment
  111.      * @param TranslatorInterface $translator
  112.      * @param string $code
  113.      *
  114.      * @return Response
  115.      * @throws Exception
  116.      */
  117.     public function thankYouPage(
  118.         EntityManagerInterface $em,
  119.         Request $request,
  120.         QrPayment $qrPayment,
  121.         TranslatorInterface $translator,
  122.         string $code
  123.     ): Response {
  124.         $session $request->getSession();
  125.         $sessionCode $session->get('code');
  126.         if (!is_null($sessionCode)) {
  127.             $session->remove('code');
  128.         }
  129.         if (is_null($sessionCode) || Tools::formatCode($sessionCode) !== $code) {
  130.             $this->addFlash('error'$translator->trans('Špatný kód objednávky!', [], 'customer'));
  131.             return $this->redirectToRoute('customer_index');
  132.         }
  133.         $config $em->getRepository(Configuration::class);
  134.         $packageCodeRepository $em->getRepository(PackageCode::class);
  135.         $packageCode $packageCodeRepository->findOneBy(['code' => str_replace('-'''$code)]);
  136.         if (is_null($packageCode)) {
  137.             throw new Exception('Nepodařilo se najít v systému kód balíku: "' $code '"!');
  138.         }
  139.         $order $packageCode->getCodeLocation()->getObject()->getOrder();
  140.         return $this->render(
  141.             'Customer/Postman/thank_you.html.twig',
  142.             [
  143.                 'order' => $order,
  144.                 'accountNumber' => $config->get('order_payment_account_czk'),
  145.                 'qrImage' => $qrPayment->createQRPaymentImageCZK($order->getPriceVat(), $order->getIdentifier()),
  146.                 'code' => $code,
  147.                 'support_postman_email' => $config->get('support_postman_email'),
  148.                 'support_postman_phone' => $config->get('support_postman_phone'),
  149.             ]
  150.         );
  151.     }
  152.     /**
  153.      * Metoda loguje neuspesne pokusy o vytvoreni objednavky
  154.      *
  155.      * @param Mailer $mailer
  156.      * @param LoggerInterface $ordersLogger
  157.      * @param TranslatorInterface $translator
  158.      * @param array $formData
  159.      * @param Throwable $throwable
  160.      *
  161.      * @return Response
  162.      */
  163.     private function logAcquisitionException(
  164.         Mailer $mailer,
  165.         LoggerInterface $ordersLogger,
  166.         TranslatorInterface $translator,
  167.         array $formData,
  168.         Throwable $throwable
  169.     ): Response {
  170.         try {
  171.             $json json_encode([
  172.                                     'calculation' => (array)$formData['calculation'],
  173.                                     'deliveryTo' => (array)$formData['deliveryTo'],
  174.                                     'returnTo' => (array)$formData['returnTo'],
  175.                                     'billing' => (array)$formData['billing'],
  176.                                     'contentDescription' => (array)$formData['contentDescription'],
  177.                                 ], JSON_THROW_ON_ERROR);
  178.         } catch (Throwable $e) {
  179.             $json 'chyba JSONu: ' $e->getMessage();
  180.         }
  181.         $ordersLogger->critical('CHYBA ULOZENI OBJEDNAVKY: ' $throwable->getMessage());
  182.         $ordersLogger->critical('Form data: ' $json);
  183.         $mailData = [
  184.             'formData' => $formData,
  185.             'throwable' => $throwable->getMessage(),
  186.             //  'request' => $request,
  187.         ];
  188.         $mailer->sendMail(
  189.             Mailer::ERROR_ADDRESS,
  190.             'Nepodařilo se uložit objednávku!',
  191.             Mailer::TEMPLATE_POSTMAN_ACQUISITION_ERROR,
  192.             $mailData
  193.         );
  194.         if ($throwable instanceof InvalidPriceException) {
  195.             $this->addFlash('error'$throwable->getMessage());
  196.         } else {
  197.             $this->addFlash(
  198.                 'error',
  199.                 $translator->trans('Při uložení objednávky se vyskytla chyba!', [], 'customer')
  200.             );
  201.         }
  202.         return $this->redirectToRoute('customer_index');
  203.     }
  204.     /**
  205.      * Metoda nastavuje vychozi zemi doruceni, ktera se urcuje temito pravidla
  206.      * 1. hledam zemi podle parametru v url
  207.      * 2. hledam zemi podle parametru v session
  208.      * 3. hledam zemi podle vychozi zeme v konfiguraci
  209.      *
  210.      * @param EntityManagerInterface $em
  211.      * @param Session $session
  212.      * @param TranslatorInterface $translator
  213.      * @param string|null $deliveryTo
  214.      *
  215.      * @return Country
  216.      * @throws \Doctrine\ORM\NonUniqueResultException
  217.      */
  218.     private function getDefaultDeliveryCountry(
  219.         EntityManagerInterface $em,
  220.         Session $session,
  221.         TranslatorInterface $translator,
  222.         ?string $deliveryTo
  223.     ): Country {
  224.         $config $em
  225.             ->getRepository(Configuration::class);
  226.         $countryRepo $em->getRepository(Country::class);
  227.         // nastavuji iso z url, pripadne z session
  228.         if (!is_null($deliveryTo)) {
  229.             $iso $deliveryTo;
  230.         } elseif ($session->get('deliveryTo')) {
  231.             $iso $session->get('deliveryTo');
  232.         }
  233.         // iso mam nastavene, ale uzivatel mohl do url nastavit neexistujii hodnotu
  234.         if (isset($iso)) {
  235.             $country $countryRepo->findActiveCountryByIso($iso);
  236.         }
  237.         if (!isset($country)) {
  238.             // pokud nebyla zeme nalezena, zkousim zachranou variantu vychozi zeme
  239.             $iso $config->get('default_delivery_country_iso');
  240.             $country $countryRepo->findActiveCountryByIso($iso);
  241.         }
  242.         if (!$country) {
  243.             // ani vychozi zeme neni nalezena (nemelo by nastavat)
  244.             throw new Exception(
  245.                 $translator->trans(
  246.                     'Nebyla naleza země!',
  247.                     [],
  248.                     'customer'
  249.                 )
  250.             );
  251.         }
  252.         $session->set('deliveryTo'$country->getIso());
  253.         return $country;
  254.     }
  255.     /**
  256.      * Ziskani noveho kodu pro balik
  257.      *
  258.      * @param EntityManagerInterface $em
  259.      * @param Session $session
  260.      * @param Mailer $mailer
  261.      *
  262.      * @return string
  263.      */
  264.     private function getPregenCodeAndSetInSession(
  265.         EntityManagerInterface $em,
  266.         Session $session,
  267.         Mailer $mailer
  268.     ): string {
  269.         $pregenCodeRepo $em
  270.             ->getRepository(PregeneratedCode::class);
  271.         $code $pregenCodeRepo->getUnusedCode();
  272.         $availableCodes $pregenCodeRepo->checkAvailableCodes();
  273.         if ($availableCodes['sendMail'] === true) {
  274.             $msg 'Zbývá jen ' $availableCodes['availableCodes']
  275.                 . ' volných kódů.';
  276.             $mailer->sendMail(
  277.                 Mailer::ERROR_ADDRESS,
  278.                 'Nedostatek volných kódů!',
  279.                 null,
  280.                 ['message' => $msg]
  281.             );
  282.         }
  283.         $session->set('code'$code);
  284.         return $code;
  285.     }
  286.     /**
  287.      * Zpracovani odeslaneho formulare:
  288.      * ulozime a zpracujeme objednavku
  289.      * odesleme objednavkovy email
  290.      * presmerujeme na thankYou
  291.      * v pripade problemu zpet na index
  292.      *
  293.      * @param FormInterface $simpleOrderForm
  294.      * @param string $code
  295.      * @param Session $session
  296.      * @param Mailer $mailer
  297.      * @param ConfigurationRepository $config
  298.      * @param TranslatorInterface $translator
  299.      * @param FlexibeeConnector $flexibeeConnector
  300.      * @param LoggerInterface $ordersLogger
  301.      * @param EntityManagerInterface $em
  302.      * @return Response
  303.      * @throws Exception
  304.      */
  305.     private function processSubmitedFormAndRedirect(
  306.         FormInterface $simpleOrderForm,
  307.         string $code,
  308.         Session $session,
  309.         Mailer $mailer,
  310.         ConfigurationRepository $config,
  311.         TranslatorInterface $translator,
  312.         FlexibeeConnector $flexibeeConnector,
  313.         LoggerInterface $ordersLogger,
  314.         EntityManagerInterface $em
  315.     ): Response {
  316.         $data
  317.             $simpleOrderForm->getData();
  318.         try {
  319.             $persistData = [
  320.                 'calculation' => $data['calculation'],
  321.                 'deliveryAddress' => $data['deliveryTo'],
  322.                 'returnAddress' => $data['returnTo'],
  323.                 'billingAddress' => $data['billing'],
  324.                 'contentDescription' => $data['contentDescription'],
  325.                 'code' => $code
  326.             ];
  327.             $orderPersist = new OrderPostmanPersist(
  328.                 $em,
  329.                 $translator,
  330.                 $persistData
  331.             );
  332.             $order $orderPersist->processAndPersistOrder();
  333.             $orderPersist->sendOrderToFlexibee($mailer$translator$flexibeeConnector);
  334.             $mailer->sendMail(
  335.                 $data['returnTo']->getEmail(),
  336.                 'Potvrzení objednávky',
  337.                 Mailer::TEMPLATE_POSTMAN_THANK_YOU,
  338.                 [
  339.                     'headline' => 'Potvrzení objednávky',
  340.                     'order' => $order,
  341.                     'accountNumber' => $config->get('order_payment_account_czk'),
  342.                     'qrImageUriHash' => $order->getProformaInvoiceHash(),
  343.                     'code' => $code,
  344.                     'depo_address_name' => $config->get('depo_address_name'),
  345.                     'depo_address_street' => $config->get('depo_address_street'),
  346.                     'depo_address_city' => $config->get('depo_address_city'),
  347.                     'depo_address_zipcode' => $config->get('depo_address_zipcode'),
  348.                     'support_postman_email' => $config->get('support_postman_email'),
  349.                     'support_postman_phone' => $config->get('support_postman_phone'),
  350.                     'depo_phone' => $config->get('depo_phone')
  351.                 ]
  352.             );
  353.         } catch (Throwable $ex) {
  354.             if (!is_null($session->get('code'))) {
  355.                 $session->remove('code');
  356.             }
  357.             return $this->logAcquisitionException(
  358.                 $mailer,
  359.                 $ordersLogger,
  360.                 $translator,
  361.                 $data,
  362.                 $ex
  363.             );
  364.         }
  365.         $this->addFlash(
  366.             'success',
  367.             $translator->trans(
  368.                 "Objednávka %identifier% byla uložena!",
  369.                 ["%identifier%" => $order->getIdentifier()],
  370.                 'customer'
  371.             )
  372.         );
  373.         return $this->redirectToRoute(
  374.             'customer_thank_you_page',
  375.             ['code' => Tools::formatCode($code)]
  376.         );
  377.     }
  378.     /**
  379.      * Metoda validuje formular premustuje prazdnou billing address
  380.      *
  381.      * @param FormInterface $simpleOrderForm
  382.      * @param TranslatorInterface $translator
  383.      * @param LoggerInterface $logger
  384.      * @return bool
  385.      */
  386.     private function simpleOrderTypeValidation(
  387.         FormInterface $simpleOrderForm,
  388.         TranslatorInterface $translator,
  389.         LoggerInterface $logger
  390.     ): bool {
  391.         // true znamena chci i errory potomku
  392.         $formErrors $simpleOrderForm->getErrors(true);
  393.         $allowedErrors = [
  394.             'data[billing].name',
  395.             'data[billing].address1',
  396.             'data[billing].city',
  397.             'data[billing].zipCode',
  398.             'data[billing].phone'
  399.         ];
  400.         $count 0;
  401.         $previousError null;
  402.         while ($formErrors->valid()) {
  403.             if ($previousError === $formErrors->current()) {
  404.                 break;
  405.             }
  406.             $previousError $formErrors->current();
  407.             try {
  408.                 //tady nam to padalo kdyz prisla CSRF chyba
  409.                 $cause $formErrors->current()->getCause()->getPropertyPath();
  410.                 $template $formErrors->current()->getMessageTemplate();
  411.             } catch (\Throwable $e) {
  412.                 if (!($formErrors->current()->getCause() instanceof CsrfToken)) {
  413.                     $this->addFlash(
  414.                         'error',
  415.                         $translator->trans('Došlo k neznámé chybě!', [], 'customer')
  416.                         . ' '
  417.                         $translator->trans('Zkuste formulář znovu odeslat.', [], 'customer')
  418.                     );
  419.                     $logger->error(
  420.                         'Neznama chyba akvizicniho formulare.',
  421.                         [
  422.                             'message' => $e->getMessage(),
  423.                             'trace' => $e->getTrace()
  424.                         ]
  425.                     );
  426.                 }
  427.                 return false;
  428.             }
  429.             // testuji, jestli je Error na polich rodice entity BillingAddress a jestli je to notBlankError
  430.             if (\in_array($cause$allowedErrors) && str_ends_with($template'notBlank')) {
  431.                 ++$count;
  432.             } else {
  433.                 return $simpleOrderForm->isValid();
  434.             }
  435.             $formErrors->next();
  436.         }
  437.         if ($simpleOrderForm instanceof Form && \count($allowedErrors) === $count) {
  438.             $simpleOrderForm->clearErrors(true);
  439.         }
  440.         return $simpleOrderForm->isValid();
  441.     }
  442.     /**
  443.      * Nacita stranku ceniku - tabulek s cenou pro kazdou zemi
  444.      * @param EntityManagerInterface $em
  445.      * @return Response
  446.      */
  447.     public function priceList(EntityManagerInterface $em): Response
  448.     {
  449.         $carrierPricePostmanRepo $em->getRepository(CarrierPricePostman::class);
  450.         $countries $carrierPricePostmanRepo->getCarrierPrices();
  451.         $output = [];
  452.         foreach ($countries as $country) {
  453.             $output[$country->getCountry()->getName()][$country->getCountry()->getIso()][$country->getWeight(
  454.             )] = $country->getPriceSell();
  455.         }
  456.         return $this->render(
  457.             'Customer/Postman/price_list.html.twig',
  458.             [
  459.                 'countries' => $output,
  460.             ]
  461.         );
  462.     }
  463. }