src/Controller/BackOffice/QuoteItemController.php line 1088

Open in your IDE?
  1. <?php
  2. namespace App\Controller\BackOffice;
  3. use App\Controller\BaseController;
  4. use App\COREapi\CoreApi;
  5. use App\COREapi\ReservationApi;
  6. use App\Entity\Currency;
  7. use App\Entity\Quote;
  8. use App\Entity\QuoteItem;
  9. use Api\Entity\Supplier;
  10. use App\Entity\User;
  11. use App\Form\CoreOffice\SupplierType;
  12. use App\Form\MyQuoteItem\MyQuoteItemType;
  13. use App\HubSpotAPI\HubSpotAPI;
  14. use App\Model\QuoteItem\CancellationPolicyModel;
  15. use App\Model\QuoteItem\MyQuoteItemModel;
  16. use App\OpenExchangeRatesAPI\OpenExchangeRates;
  17. use App\QuickbooksAPI\QuickbooksAPI;
  18. use App\Repository\QuoteItemRepository;
  19. use App\Repository\QuoteRepository;
  20. use App\Reservation\ReservationFactory;
  21. use Doctrine\ORM\EntityManagerInterface;
  22. use finfo;
  23. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  24. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  25. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  26. use Symfony\Component\Filesystem\Filesystem;
  27. use Symfony\Component\Form\FormErrorIterator;
  28. use Symfony\Component\Form\FormInterface;
  29. use Symfony\Component\HttpFoundation\File\UploadedFile;
  30. use Symfony\Component\HttpFoundation\RedirectResponse;
  31. use Symfony\Component\HttpFoundation\Request;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\HttpFoundation\JsonResponse;
  34. use Symfony\Component\Routing\Annotation\Route;
  35. use Symfony\Component\Validator\ConstraintViolation;
  36. use App\NotificationSystem\NotificationSystem;
  37. /**
  38.  * @Route("/backoffice/quoteItem")
  39.  * @Security("is_granted('IS_AUTHENTICATED_FULLY')")
  40.  */
  41. class QuoteItemController extends BaseController
  42. {
  43.     /**
  44.      * @Route("/sort/update", name="quoteItems_sort_update", methods={"POST"})
  45.      * @param Request $request
  46.      * @param QuoteItemRepository $quoteItemRepository
  47.      */
  48.     public function quoteItemsSortUpdateAction(Request $requestQuoteItemRepository $quoteItemRepository): Response
  49.     {
  50.         try {
  51.             $quoteItemsToUpdate $request->request->get('quoteItems');
  52.             $em $this->getDoctrine()->getManager();
  53.             foreach ($quoteItemsToUpdate as $quoteItemToUpdate) {
  54.                 if ($quoteItem $quoteItemRepository->find($quoteItemToUpdate['id'])) {
  55.                     $quoteItem->setSort($quoteItemToUpdate['sort']);
  56.                     $em->persist($quoteItem);
  57.                     $em->flush();
  58.                 }
  59.             }
  60.             return $this->json(array('status' => 'success'));
  61.         } catch (\Exception $e) {
  62.             return $this->json(array(
  63.                 "message" => $e->getMessage()
  64.             ), 400);
  65.         }
  66.     }
  67.     /**
  68.      * @Route("/name/update", name="quoteItems_name_update", methods={"POST"})
  69.      * @param Request $request
  70.      * @param QuoteRepository $quoteRepository
  71.      * @return Response
  72.      */
  73.     public function quoteItemsNameUpdateAction(Request $requestQuoteRepository $quoteRepository): Response
  74.     {
  75.         try {
  76.             $idQuote $request->request->get('idQuote');
  77.             $lastNameToCopy trim($request->request->get('lastNameToCopy'));
  78.             $nameToCopy trim($request->request->get('nameToCopy'));
  79.             $overwriteAllName trim($request->request->get('overwriteAllName'));
  80.             if (!$quote $quoteRepository->find($idQuote)) {
  81.                 throw new \Exception('Quote was not found');
  82.             }
  83.             $em $this->getDoctrine()->getManager();
  84.             $i 0;
  85.             foreach ($quote->getQuoteItems() as $quoteItem) {
  86.                 if (!$quoteItem->isBooked() && ($overwriteAllName || !trim($quoteItem->getClientFullName()))) {
  87.                     $quoteItem->resetClientNameAndLastNameJson();
  88.                     $quoteItem->setClientName($nameToCopy);
  89.                     $quoteItem->setClientLastName($lastNameToCopy);
  90.                     $i++;
  91.                     $em->persist($quoteItem);
  92.                     $em->flush();
  93.                 }
  94.             }
  95.             if ($i) {
  96.                 $this->addFlash('success''The name has been Successfully updated for Quote #' $quote->getQuoteNumber() . " - " $quote->getDescription());
  97.             } else {
  98.                 $this->addFlash('warning''There were no quote items to be updated for Quote #' $quote->getQuoteNumber());
  99.             }
  100.         } catch (\Exception $e) {
  101.             $this->addFlash('error'"The Quote couldn't be updated. Error: " $e->getMessage());
  102.         }
  103.         //Redirect to previous page
  104.         if ($url $request->headers->get('referer')) {
  105.             $url str_replace($request->getSchemeAndHttpHost(), ""$url);
  106.             return new RedirectResponse($url);
  107.         }
  108.         return $this->redirectToRoute('quote_edit', array('id' => $idQuote));
  109.     }
  110.     /**
  111.      * @Route("/newActivity/{quote}", name="my_quoteItem_new_activity", methods={"GET","POST"})
  112.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  113.      * @param Request $request
  114.      * @param Quote $quote
  115.      * @param QuickbooksAPI $quickbooksAPI
  116.      * @param ReservationFactory $reservationFactory
  117.      * @param NotificationSystem $notificationSystem
  118.      * @param CoreApi $coreApi
  119.      * @return Response
  120.      */
  121.     public function newActivity(Request $requestQuote $quoteQuickbooksAPI $quickbooksAPIReservationFactory $reservationFactoryNotificationSystem $notificationSystemCoreApi $coreApiHubSpotAPI $hubSpotAPIReservationApi $reservationApi): Response
  122.     {
  123.         locale_set_default('en-US');
  124.         $quoteItem = new QuoteItem();
  125.         $quoteItem->setQuote($quote);
  126.         //By default, one day
  127.         $quoteStart $quote->getStartDate() ? $quote->getStartDate() : new \DateTime('now');
  128.         $date = new \DateTime('now');
  129.         $checkIn max($quoteStart$date);
  130.         $quoteItem->setCheckIn($checkIn);
  131.         $quoteItem->setCheckOut($checkIn);
  132.         $quoteItem->setType(QuoteItem::PRODUCT_TYPE_ACTIVITY);
  133.         $quoteItem->setSource(QuoteItem::PRODUCT_SOURCE_MANUALLY);
  134.         $quoteItem->setIdProduct(0); //Dummy value for test 171783
  135.         $quoteItem->setReservationNotBookStatus();
  136.         $quoteItem->setAccountingPendingStatus();
  137.         $quoteItem->setPriceRefreshAt(new \DateTime('now'));
  138.         $quoteItem->setIsPriceRefresh(true);
  139.         $quoteItem->setRetailIsCustomized(true);
  140.         $quoteItem->setShowRatesInOneLine(true);
  141.         $quoteItem->setAdditionalInformation(array("manuallyAdded" => true));
  142.         $quoteItem->setDisplayInOriginalCurrency(false);
  143.         $requestArray $request->request->all();
  144.         if (array_key_exists('my_quote_item'$requestArray)) {
  145.             $quoteItem->setNumberOfAdults($requestArray['my_quote_item']['quoteItem']['quantity']);
  146.             if (!is_numeric($requestArray['my_quote_item']['quoteItem']['vendorId'])) {
  147.                 unset($requestArray['my_quote_item']['quoteItem']['vendorId']);
  148.                 $request->request->set('my_quote_item'$requestArray['my_quote_item']);
  149.             }
  150.         }
  151.         $this->setOriginalCurrencyObj($request$quoteItem);
  152.         $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  153.         $this->setCancellationPolicyFrontEnd($quoteItem$cancellationPolicyFrontEnd);
  154.         $supplierCancellationPolicyFrontEnds = array();
  155.         $oxCancellationPolicyFrontEnds = array();
  156.         $quoteItem->setSupplierCancellationPolicyWasMissing(true);
  157.         $this->setCancellationPolicyFrontEnds($quoteItem$request$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  158. //        if (array_key_exists('my_quote_item', $requestArray) && $requestArray['my_quote_item']['useOxCancellationPolicy']){
  159. //            foreach ($oxCancellationPolicyFrontEnds as $oxCancellationPolicyFrontEnd) {
  160. //                $cancellationPolicyFrontEnd = $oxCancellationPolicyFrontEnd;
  161. //            }
  162. //        }else{
  163. //            foreach ($supplierCancellationPolicyFrontEnds as $supplierCancellationPolicyFrontEnd) {
  164. //                $cancellationPolicyFrontEnd = $supplierCancellationPolicyFrontEnd;
  165. //            }
  166. //        }
  167.         $myQuoteItem = new MyQuoteItemModel($quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  168.         $options = array('product' => QuoteItem::PRODUCT_TYPE_ACTIVITY);
  169.         $originalQuoteItem = clone($quoteItem);
  170.         $form $this->createForm(MyQuoteItemType::class, $myQuoteItem$options);
  171.         $form->handleRequest($request);
  172.         try {
  173.             $quoteItem $myQuoteItem->getQuoteItem();
  174.             $this->saveQuoteItem($request$form$quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds$originalQuoteItem'added'$quickbooksAPI$reservationFactory$notificationSystem$coreApi$hubSpotAPI$reservationApi);
  175.             if ($quoteItem->getId()) {
  176.                 //It was created the activity, redirect to My Quote Item edit view
  177.                 return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  178.             }
  179.         } catch (\Exception $e) {
  180.             $this->addFlash('error'"<p>The Activity couldn't be saved.</p><p></p> Error&colon; <br/>" $e->getMessage() . "</p>");
  181.         }
  182.         $em $this->getDoctrine()->getManager();
  183.         $exchangeRateData $em->getRepository(Currency::class)->getRatesByShortName();
  184.         $supplier = new Supplier();
  185.         $formSupplier $this->createForm(SupplierType::class, $supplier);
  186.         $formSupplier->handleRequest($request);
  187.         return $this->render('backOffice/myQuote/edit.html.twig', [
  188.             'formMyQuoteItem' => $form->createView(),
  189.             'quoteItem' => $quoteItem,
  190.             'title' => 'New Activity',
  191.             'supplier' => $supplier,
  192.             'formSupplier' => $formSupplier->createView(),
  193.             'exchangeRateData' => $exchangeRateData,
  194.             'hasQuoteCommission' => !!$quoteItem->getQuote()->getCustomerAccountCommissionType(),
  195.         ]);
  196.     }
  197.     /**
  198.      * @Route("/newVilla/{quote}", name="my_quoteItem_new_villa", methods={"GET","POST"})
  199.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  200.      * @param Request $request
  201.      * @param Quote $quote
  202.      * @param QuickbooksAPI $quickbooksAPI
  203.      * @param ReservationFactory $reservationFactory
  204.      * @param NotificationSystem $notificationSystem
  205.      * @param CoreApi $coreApi
  206.      * @return Response
  207.      */
  208.     public function newVilla(Request $requestQuote $quoteQuickbooksAPI $quickbooksAPIReservationFactory $reservationFactoryNotificationSystem $notificationSystemCoreApi $coreApiHubSpotAPI $hubSpotAPIReservationApi $reservationApi): Response
  209.     {
  210.         locale_set_default('en-US');
  211.         $quoteItem = new QuoteItem();
  212.         $quoteItem->setQuote($quote);
  213.         //By default, one day
  214.         $quoteStart $quote->getStartDate() ? $quote->getStartDate() : new \DateTime('now');
  215.         $date = new \DateTime('now');
  216.         $checkIn max($quoteStart$date);
  217.         $quoteItem->setCheckIn($checkIn);
  218.         $quoteItem->setCheckOut($checkIn);
  219.         $quoteItem->setType(QuoteItem::PRODUCT_TYPE_VILLA);
  220.         $quoteItem->setSource(QuoteItem::PRODUCT_SOURCE_MANUALLY);
  221.         $quoteItem->setIdProduct(0); //Dummy value for test 171783
  222.         $quoteItem->setReservationNotBookStatus();
  223.         $quoteItem->setAccountingPendingStatus();
  224.         $quoteItem->setPriceRefreshAt(new \DateTime('now'));
  225.         $quoteItem->setIsPriceRefresh(true);
  226.         $quoteItem->setRetailIsCustomized(true);
  227.         $quoteItem->setShowRatesInOneLine(true);
  228.         $quoteItem->setAdditionalInformation(array("manuallyAdded" => true));
  229.         $quoteItem->setDisplayInOriginalCurrency(false);
  230.         $requestArray $request->request->all();
  231.         if (array_key_exists('my_quote_item'$requestArray)) {
  232.             $quoteItem->setNumberOfAdults($requestArray['my_quote_item']['quoteItem']['quantity']);
  233.             if (!is_numeric($requestArray['my_quote_item']['quoteItem']['vendorId'])) {
  234.                 unset($requestArray['my_quote_item']['quoteItem']['vendorId']);
  235.                 $request->request->set('my_quote_item'$requestArray['my_quote_item']);
  236.             }
  237.         }
  238.         $this->setOriginalCurrencyObj($request$quoteItem);
  239.         $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  240.         $this->setCancellationPolicyFrontEnd($quoteItem$cancellationPolicyFrontEnd);
  241.         $supplierCancellationPolicyFrontEnds = array();
  242.         $oxCancellationPolicyFrontEnds = array();
  243.         $quoteItem->setSupplierCancellationPolicyWasMissing(true);
  244.         $this->setCancellationPolicyFrontEnds($quoteItem$request$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  245. //        if (array_key_exists('my_quote_item', $requestArray) && $requestArray['my_quote_item']['useOxCancellationPolicy']){
  246. //            foreach ($oxCancellationPolicyFrontEnds as $oxCancellationPolicyFrontEnd) {
  247. //                $cancellationPolicyFrontEnd = $oxCancellationPolicyFrontEnd;
  248. //            }
  249. //        }else{
  250. //            foreach ($supplierCancellationPolicyFrontEnds as $supplierCancellationPolicyFrontEnd) {
  251. //                $cancellationPolicyFrontEnd = $supplierCancellationPolicyFrontEnd;
  252. //            }
  253. //        }
  254.         $myQuoteItem = new MyQuoteItemModel($quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  255.         $options = array('product' => QuoteItem::PRODUCT_TYPE_VILLA);
  256.         $originalQuoteItem = clone($quoteItem);
  257.         $form $this->createForm(MyQuoteItemType::class, $myQuoteItem$options);
  258.         $form->handleRequest($request);
  259.         try {
  260.             $quoteItem $myQuoteItem->getQuoteItem();
  261.             $this->saveQuoteItem($request$form$quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds$originalQuoteItem'added'$quickbooksAPI$reservationFactory$notificationSystem$coreApi$hubSpotAPI$reservationApi);
  262.             if ($quoteItem->getId()) {
  263.                 //It was created the activity, redirect to My Quote Item edit view
  264.                 return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  265.             }
  266.         } catch (\Exception $e) {
  267.             $this->addFlash('error'"<p>The Villa couldn't be saved.</p><p></p> Error&colon; <br/>" $e->getMessage() . "</p>");
  268.         }
  269.         $em $this->getDoctrine()->getManager();
  270.         $exchangeRateData $em->getRepository(Currency::class)->getRatesByShortName();
  271.         $supplier = new Supplier();
  272.         $formSupplier $this->createForm(SupplierType::class, $supplier);
  273.         $formSupplier->handleRequest($request);
  274.         return $this->render('backOffice/myQuote/edit.html.twig', [
  275.             'formMyQuoteItem' => $form->createView(),
  276.             'quoteItem' => $quoteItem,
  277.             'title' => 'New Activity',
  278.             'supplier' => $supplier,
  279.             'formSupplier' => $formSupplier->createView(),
  280.             'exchangeRateData' => $exchangeRateData,
  281.             'hasQuoteCommission' => !!$quoteItem->getQuote()->getCustomerAccountCommissionType(),
  282.         ]);
  283.     }
  284.     /**
  285.      * @Route("/newTransfer/{quote}", name="my_quoteItem_new_transfer", methods={"GET","POST"})
  286.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  287.      * @param Request $request
  288.      * @param Quote $quote
  289.      * @return Response
  290.      */
  291.     public function newTransfer(Request $requestQuote $quoteQuickbooksAPI $quickbooksAPIReservationFactory $reservationFactoryNotificationSystem $notificationSystemCoreApi $coreApiHubSpotAPI $hubSpotAPIReservationApi $reservationApi): Response
  292.     {
  293.         locale_set_default('en-US');
  294.         $quoteItem = new QuoteItem();
  295.         $quoteItem->setQuote($quote);
  296.         //By default one day
  297.         $quoteStart $quote->getStartDate() ? $quote->getStartDate() : new \DateTime('now');
  298.         $date = new \DateTime('now');
  299.         $checkIn max($quoteStart$date);
  300.         $quoteItem->setCheckIn($checkIn);
  301.         $quoteItem->setCheckOut($checkIn);
  302.         $dateStr $quoteItem->getDateToStr($checkIn);
  303.         $timeStr "11:00 AM";//Default
  304.         $quoteItem->setIdProduct(0); //Dummy value for test 106510
  305.         $quoteItem->setType(QuoteItem::PRODUCT_TYPE_TRANSFER);
  306.         $quoteItem->setSource(QuoteItem::PRODUCT_SOURCE_MANUALLY);
  307.         $quoteItem->setReservationNotBookStatus();
  308.         $quoteItem->setAccountingPendingStatus();
  309.         $quoteItem->setPriceRefreshAt(new \DateTime('now'));
  310.         $quoteItem->setIsPriceRefresh(true);
  311.         $quoteItem->setRetailIsCustomized(true);
  312.         $quoteItem->setShowRatesInOneLine(false);
  313.         $quoteItem->setDisplayInOriginalCurrency(false);
  314.         $quoteItem->setAdditionalInformation(array(
  315.                 "manuallyAdded" => true,
  316.                 "transfer" => array(),
  317.                 "transferDate" => $dateStr,
  318.                 "transferTime" => $timeStr,
  319.                 "transferAddress" => "")
  320.         );
  321.         $this->setOriginalCurrencyObj($request$quoteItem);
  322.         $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  323.         $this->setCancellationPolicyFrontEnd($quoteItem$cancellationPolicyFrontEnd);
  324.         $supplierCancellationPolicyFrontEnds = array();
  325.         $oxCancellationPolicyFrontEnds = array();
  326.         $quoteItem->setSupplierCancellationPolicyWasMissing(true);
  327.         $this->setCancellationPolicyFrontEnds($quoteItem$request$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  328. //        $requestArray = $request->request->all();
  329. //        if (array_key_exists('my_quote_item', $requestArray) && $requestArray['my_quote_item']['useOxCancellationPolicy']){
  330. //            $cancellationPolicyFrontEnd = $oxCancellationPolicyFrontEnds[0];
  331. //        }else{
  332. //            $cancellationPolicyFrontEnd = $supplierCancellationPolicyFrontEnds[0];
  333. //        }
  334.         $myQuoteItem = new MyQuoteItemModel($quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  335.         $options = array('product' => QuoteItem::PRODUCT_TYPE_TRANSFER);
  336.         $originalQuoteItem = clone($quoteItem);
  337.         $form $this->createForm(MyQuoteItemType::class, $myQuoteItem$options);
  338.         $form->handleRequest($request);
  339.         try {
  340.             $quoteItem $myQuoteItem->getQuoteItem();
  341.             $this->saveQuoteItem($request$form$quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds$originalQuoteItem'added'$quickbooksAPI$reservationFactory$notificationSystem$coreApi$hubSpotAPI$reservationApi);
  342.             if ($quoteItem->getId()) {
  343.                 //It was created the activity, redirect to My Quote Item edit view
  344.                 return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  345.             }
  346.         } catch (\Exception $e) {
  347.             $this->addFlash('error'"<p>The Transfer couldn't be saved.</p><p></p> Error&colon; <br/>" $e->getMessage() . "</p>");
  348.         }
  349.         $em $this->getDoctrine()->getManager();
  350.         $exchangeRateData $em->getRepository(Currency::class)->getRatesByShortName();
  351.         $supplier = new Supplier();
  352.         $formSupplier $this->createForm(SupplierType::class, $supplier);
  353.         $formSupplier->handleRequest($request);
  354.         return $this->render('backOffice/myQuote/edit.html.twig', [
  355.             'formMyQuoteItem' => $form->createView(),
  356.             'quoteItem' => $quoteItem,
  357.             'title' => 'New Transfer',
  358.             'supplier' => $supplier,
  359.             'formSupplier' => $formSupplier->createView(),
  360.             'exchangeRateData' => $exchangeRateData,
  361.             'hasQuoteCommission' => !!$quoteItem->getQuote()->getCustomerAccountCommissionType(),
  362.         ]);
  363.     }
  364.     /**
  365.      * @Route("/newCarRental/{quote}", name="my_quoteItem_new_car_rental", methods={"GET","POST"})
  366.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  367.      * @param Request $request
  368.      * @param Quote $quote
  369.      * @return Response
  370.      */
  371.     public function newCarRental(Request $requestQuote $quoteQuickbooksAPI $quickbooksAPIReservationFactory $reservationFactoryNotificationSystem $notificationSystemCoreApi $coreApiHubSpotAPI $hubSpotAPIReservationApi $reservationApi): Response
  372.     {
  373.         locale_set_default('en-US');
  374.         $quoteItem = new QuoteItem();
  375.         $quoteItem->setQuote($quote);
  376.         //By default, one day
  377.         $quoteStart $quote->getStartDate() ? $quote->getStartDate() : new \DateTime('now');
  378.         $date = new \DateTime('now');
  379.         $checkIn max($quoteStart$date);
  380.         $quoteItem->setCheckIn($checkIn);
  381.         $quoteItem->setCheckOut($checkIn);
  382.         $dateStr $quoteItem->getDateToStr($checkIn);
  383.         $timeStr "TBC";//Default
  384.         $quoteItem->setIdProduct(0); //Dummy value for test 106510
  385.         $quoteItem->setType(QuoteItem::PRODUCT_TYPE_CAR_RENTAL);
  386.         $quoteItem->setSource(QuoteItem::PRODUCT_SOURCE_MANUALLY);
  387.         $quoteItem->setNumberOfAdults(1);
  388.         $quoteItem->setReservationNotBookStatus();
  389.         $quoteItem->setAccountingPendingStatus();
  390.         $quoteItem->setPriceRefreshAt(new \DateTime('now'));
  391.         $quoteItem->setIsPriceRefresh(true);
  392.         $quoteItem->setRetailIsCustomized(true);
  393.         $quoteItem->setShowRatesInOneLine(false);
  394.         $quoteItem->setDisplayInOriginalCurrency(false);
  395.         $quoteItem->setAdditionalInformation(array(
  396.                 "manuallyAdded" => true,
  397.                 "pickupDate" => $dateStr,
  398.                 "pickupTime" => $timeStr,
  399.                 "dropoffDate" => $dateStr,
  400.                 "dropoffTime" => $timeStr,
  401.                 "department" => null,
  402.             )
  403.         );
  404.         $this->setOriginalCurrencyObj($request$quoteItem);
  405.         $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  406.         $this->setCancellationPolicyFrontEnd($quoteItem$cancellationPolicyFrontEnd);
  407.         $supplierCancellationPolicyFrontEnds = array();
  408.         $oxCancellationPolicyFrontEnds = array();
  409.         $quoteItem->setSupplierCancellationPolicyWasMissing(true);
  410.         $this->setCancellationPolicyFrontEnds($quoteItem$request$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  411. //        $requestArray = $request->request->all();
  412. //        if (array_key_exists('my_quote_item', $requestArray) && $requestArray['my_quote_item']['useOxCancellationPolicy']){
  413. //            $cancellationPolicyFrontEnd = $oxCancellationPolicyFrontEnds[0];
  414. //        }else{
  415. //            $cancellationPolicyFrontEnd = $supplierCancellationPolicyFrontEnds[0];
  416. //        }
  417.         $myQuoteItem = new MyQuoteItemModel($quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  418.         // , $supplierCancellationPolicyFrontEnds, $oxCancellationPolicyFrontEnds,
  419.         $options = array('product' => QuoteItem::PRODUCT_TYPE_CAR_RENTAL);
  420.         $originalQuoteItem = clone($quoteItem);
  421.         $form $this->createForm(MyQuoteItemType::class, $myQuoteItem$options);
  422.         $form->handleRequest($request);
  423.         try {
  424.             $quoteItem $myQuoteItem->getQuoteItem();
  425.             $additionalInformation $quoteItem->getAdditionalInformation();
  426.             if (!key_exists('pickupTime'$additionalInformation)) {
  427.                 $quoteItem->setAdditionalInformation(['pickupTime' => null]);
  428.             }
  429.             if (!key_exists('dropoffTime'$additionalInformation)) {
  430.                 $quoteItem->setAdditionalInformation(['dropoffTime' => null]);
  431.             }
  432.             $this->saveQuoteItem($request$form$quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds$originalQuoteItem'added'$quickbooksAPI$reservationFactory$notificationSystem$coreApi$hubSpotAPI$reservationApi);
  433.             if ($quoteItem->getId()) {
  434.                 //It was created the car rental, redirect to My Quote Item edit view
  435.                 return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  436.             }
  437.         } catch (\Exception $e) {
  438.             $this->addFlash('error'"<p>The Car Rental couldn't be saved.</p><p></p> Error&colon; <br/>" $e->getMessage() . "</p>");
  439.         }
  440.         $em $this->getDoctrine()->getManager();
  441.         $exchangeRateData $em->getRepository(Currency::class)->getRatesByShortName();
  442.         $supplier = new Supplier();
  443.         $formSupplier $this->createForm(SupplierType::class, $supplier);
  444.         $formSupplier->handleRequest($request);
  445.         return $this->render('backOffice/myQuote/edit.html.twig', [
  446.             'formMyQuoteItem' => $form->createView(),
  447.             'quoteItem' => $quoteItem,
  448.             'title' => 'New Transfer',
  449.             'supplier' => $supplier,
  450.             'formSupplier' => $formSupplier->createView(),
  451.             'exchangeRateData' => $exchangeRateData,
  452.             'hasQuoteCommission' => !!$quoteItem->getQuote()->getCustomerAccountCommissionType(),
  453.         ]);
  454.     }
  455.     /**
  456.      * @Route("/newHotelService/{parentQuoteItem}/{type}", defaults={"type"="service"} ,name="quoteItem_new_hotel_service", methods={"GET","POST"})
  457.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  458.      * @param Request $request
  459.      * @param QuoteItem $parentQuoteItem
  460.      * @param string $type
  461.      * @return Response
  462.      */
  463.     public function newHotelService(Request $requestQuoteItem $parentQuoteItemstring $typeQuickbooksAPI $quickbooksAPIReservationFactory $reservationFactoryNotificationSystem $notificationSystemCoreApi $coreApiHubSpotAPI $hubSpotAPIReservationApi $reservationApi): Response
  464.     {
  465.         locale_set_default('en-US');
  466.         $options = array();
  467.         $quote $parentQuoteItem->getQuote();
  468.         $quoteItem = new QuoteItem();
  469.         $quoteItem->setQuote($quote);
  470.         //By default, one day
  471.         $quoteItem->setCheckIn($parentQuoteItem->getCheckIn());
  472.         $quoteItem->setCheckOut($parentQuoteItem->getCheckOut());
  473.         $quoteItem->setOriginalCurrency($parentQuoteItem->getOriginalCurrency());
  474.         $quoteItem->setDisplayInOriginalCurrency($parentQuoteItem->getDisplayInOriginalCurrency() ?? false);
  475.         $quoteItem->setExchangeRate($parentQuoteItem->getExchangeRate());
  476.         //Default
  477.         $title 'Hotel Service';
  478.         $quoteItem->setType(QuoteItem::PRODUCT_TYPE_HOTEL_SERVICE);
  479.         if ($type == 'resortFee') {
  480.             $title 'Resort Fee';
  481.             $quoteItem->setType(QuoteItem::PRODUCT_TYPE_HOTEL_RESORT_FEE);
  482.             $quoteItem->setName('Resort Fee');
  483.         }
  484.         if (in_array($type, array('resortFee''service''hotel_service'))) {
  485.             //Safe the same cancellation policy we have in the parent item (hotel)
  486.             $quoteItem->setCancellationPolicy($parentQuoteItem->getCancellationPolicy());
  487.             $quoteItem->setCancellationPolicySupplier($parentQuoteItem->getCancellationPolicySupplier());
  488.             $quoteItem->setCancellationPolicyOx($parentQuoteItem->getCancellationPolicyOx());
  489.             $quoteItem->setUseOxCancellationPolicy($parentQuoteItem->getUseOxCancellationPolicy());
  490.             $quoteItem->setCancellationPenaltyDate($parentQuoteItem->getCancellationPenaltyDate());
  491.             $quoteItem->setCancellationPenaltyId($parentQuoteItem->getCancellationPenaltyId());
  492.             $quoteItem->setCancellationPolicyLabel($parentQuoteItem->getCancellationPolicyLabels() ?? "");
  493.             //Cancellation policy should be disabled.
  494.             $options = array('disabledCancellationPolicy' => true);
  495.         }
  496.         $options['product'] = $quoteItem->getType();
  497.         $quoteItem->setSource(QuoteItem::PRODUCT_SOURCE_MANUALLY);
  498.         $quoteItem->setIdProduct(0); //Dummy value for test
  499.         $quoteItem->setQuantity(1);
  500.         $quoteItem->setReservationNotBookStatus();
  501.         $quoteItem->setAccountingPendingStatus();
  502.         $quoteItem->setClientNameJson($parentQuoteItem->getClientNameJson());
  503.         $quoteItem->setClientLastNameJson($parentQuoteItem->getClientLastNameJson());
  504.         $quoteItem->setPriceRefreshAt(new \DateTime('now'));
  505.         $quoteItem->setIsPriceRefresh(true);
  506.         $quoteItem->setRetailIsCustomized(true);
  507.         $quoteItem->setShowRatesInOneLine(false);
  508.         $quoteItem->setAdditionalInformation(array("manuallyAdded" => true));
  509.         $quoteItem->setNumberOfAdults($parentQuoteItem->getNumberOfAdults());
  510.         $quoteItem->setParentQuoteItem($parentQuoteItem);
  511.         $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  512.         $this->setCancellationPolicyFrontEnd($quoteItem$cancellationPolicyFrontEnd);
  513.         $supplierCancellationPolicyFrontEnds = array();
  514.         $oxCancellationPolicyFrontEnds = array();
  515.         $this->setCancellationPolicyFrontEnds($quoteItem$request$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  516.         $myQuoteItem = new MyQuoteItemModel($quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  517.         $originalQuoteItem = clone($quoteItem);
  518.         $form $this->createForm(MyQuoteItemType::class, $myQuoteItem$options);
  519.         $requestArray $request->request->all();
  520.         $requestArray['my_quote_item']['quoteItem']['clientNameJson'] = $parentQuoteItem->getClientNameJson();
  521.         $requestArray['my_quote_item']['quoteItem']['clientLastNameJson'] = $parentQuoteItem->getClientLastNameJson();
  522.         $request->request->set('my_quote_item'$requestArray['my_quote_item']);
  523.         $form->handleRequest($request);
  524.         try {
  525.             $quoteItem $myQuoteItem->getQuoteItem();
  526.             $this->saveQuoteItem($request$form$quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds$originalQuoteItem'added'$quickbooksAPI$reservationFactory$notificationSystem$coreApi$hubSpotAPI$reservationApi);
  527.             if ($quoteItem->getId()) {
  528.                 //It was created the hotel service, redirect to My Quote Item edit view
  529.                 return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  530.             }
  531.         } catch (\Exception $e) {
  532.             $this->addFlash('error'"<p>The " $title " couldn't be saved.</p><p></p> Error&colon; <br/>" $e->getMessage() . "</p>");
  533.         }
  534.         return $this->render('backOffice/myQuote/edit.html.twig', [
  535.             'formMyQuoteItem' => $form->createView(),
  536.             'quoteItem' => $quoteItem,
  537.             'title' => $title,
  538.             'exchangeRateData' => $parentQuoteItem->getExchangeRate(),
  539.             'hasQuoteCommission' => !!$quoteItem->getQuote()->getCustomerAccountCommissionType(),
  540.         ]);
  541.     }
  542.     /**
  543.      * @Route("/customizeRates",name="quoteItem_customize_rates", methods={"POST"})
  544.      * @Security("is_granted('ROLE_DISCONECT_RATE')")
  545.      * @param Request $request
  546.      * @param CoreApi $coreApi
  547.      * @param QuoteItemRepository $quoteItemRepository
  548.      * @return Response
  549.      */
  550.     public function customizeRates(Request $requestCoreApi $coreApiQuoteItemRepository $quoteItemRepository): Response
  551.     {
  552.         try {
  553.             //This is the Flow:
  554.             //1. Click on the button "Customized Rates"
  555.             //2. Show confirmation message: Cancel or Continue
  556.             //If they click on Continue, THEN:
  557.             //1. Change  Source to Manually
  558.             //2. Call API to get NEW product id
  559.             //3. Set NetIsCustomized to true
  560.             //4. Set CommissionIsCustomized to true
  561.             //5. Update quote item with NEW product id
  562.             //6. Reload Quote Item view with inputs enabled...
  563.             if (!$quoteItem $quoteItemRepository->find($request->request->get('id'))) {
  564.                 throw new \Exception("Quote Item is not valid.");
  565.             }
  566.             if (!$quoteItem->isHotel() || $quoteItem->isManuallyAdded()) {
  567.                 throw new \Exception("This Quote Item cannot have customize rates.");
  568.             }
  569.             if (!$coreApi->customizeRates($quoteItem)) {
  570.                 throw new \Exception($coreApi->getErrorStr());
  571.             }
  572.             //Change to manually
  573.             $quoteItem->setIsCustomizeRate(true);
  574.             $quoteItem->setSource(QuoteItem::PRODUCT_SOURCE_MANUALLY);
  575.             $em $this->getDoctrine()->getManager();
  576.             $em->persist($quoteItem);
  577.             $em->flush();
  578.             $em->refresh($quoteItem);
  579.             $this->addFlash('success''The Quote Item has been updated to allow customize rates.');
  580.         } catch (\Exception $e) {
  581.             $this->addFlash('error'"Customize rates failed. Detail: " $e->getMessage());
  582.             if (!isset($quoteItem) || !$quoteItem) {
  583.                 //Redirect to previous page
  584.                 if ($url $request->headers->get('referer')) {
  585.                     $url str_replace($request->getSchemeAndHttpHost(), ""$url);
  586.                     return new RedirectResponse($url);
  587.                 }
  588.             }
  589.         }
  590.         return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  591.     }
  592.     /**
  593.      * @Route("/edit/{id}", name="my_quoteItem_edit", methods={"GET","POST"})
  594.      * @Security("is_granted('ROLE_QUOTE_EDIT_ALL')")
  595.      * @param Request $request
  596.      * @param CoreApi $coreApi
  597.      * @param QuickbooksAPI $quickbooksAPI
  598.      * @param QuoteItem|null $quoteItem
  599.      * @param ReservationFactory $reservationFactory
  600.      * @param NotificationSystem $notificationSystem
  601.      * @param HubSpotAPI $hubSpotAPI
  602.      * @return Response
  603.      */
  604.     public function edit(Request $requestCoreApi $coreApiQuickbooksAPI $quickbooksAPIQuoteItem $quoteItem nullReservationFactory $reservationFactoryNotificationSystem $notificationSystemHubSpotAPI $hubSpotAPIReservationApi $reservationApi): Response
  605.     {
  606.         locale_set_default('en-US');
  607.         try {
  608.             $this->checkIfGrantedToSeeQuote($quoteItem->getQuote());
  609.         } catch (\Exception $e) {
  610.             $this->addFlash('warning'$e->getMessage());
  611.             return $this->redirectToRoute('all_quotes_index');
  612.         }
  613.         $options = array('product' => $quoteItem->getType(), 'disabledCancellationPolicy' => !$quoteItem->canCancellationPolicyBeUpdated(), 'showCancellationNumber' => $quoteItem->isCancelled());
  614.         if ($quoteItem->getAdditionalInformation()) {
  615.             if (isset($quoteItem->getAdditionalInformation()['pickupTime']) && is_array($quoteItem->getAdditionalInformation()['pickupTime'])) {
  616.                 $newDateTime = new \DateTime();
  617.                 $quoteItem->setAdditionalInformation(['pickupTime' => null]);
  618.             }
  619.         }
  620.         if ($quoteItem->getAdditionalInformation()) {
  621.             if (isset($quoteItem->getAdditionalInformation()['dropoffTime']) && is_array($quoteItem->getAdditionalInformation()['dropoffTime'])) {
  622.                 $newDateTime = new \DateTime();
  623.                 $quoteItem->setAdditionalInformation(['dropoffTime' => null]);
  624.             }
  625.         }
  626.         if (in_array($quoteItem->getType(), ['resortFee''hotel_service'])) {
  627.             //Safe the same cancellation policy we have in the parent item (hotel)
  628.             $parentQuoteItem $this->getDoctrine()->getRepository(QuoteItem::class)->findOneBy(array('id' => $quoteItem->getParentQuoteItem()->getId()));
  629.             $quoteItem->setCancellationPolicy($parentQuoteItem->getCancellationPolicy());
  630.             $quoteItem->setCancellationPenaltyDate($parentQuoteItem->getCancellationPenaltyDate());
  631.             $quoteItem->setCancellationPenaltyId($parentQuoteItem->getCancellationPenaltyId());
  632.             $quoteItem->setCancellationPolicyLabel($parentQuoteItem->getCancellationPolicyLabels() ?? "");
  633.             $quoteItem->setUseOxCancellationPolicy($parentQuoteItem->getUseOxCancellationPolicy() ?? false);
  634.             //Cancellation policy should be disabled.
  635.             $quoteItem->setOriginalCurrency($parentQuoteItem->getOriginalCurrency());
  636.             $quoteItem->setDisplayInOriginalCurrency($parentQuoteItem->getDisplayInOriginalCurrency() ?? false);
  637.             $quoteItem->setExchangeRate($parentQuoteItem->getExchangeRate());
  638.             $options['disabledCancellationPolicy'] = true;
  639.         }
  640.         $this->setOriginalCurrencyObj($request$quoteItem);
  641.         $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  642.         $this->setCancellationPolicyFrontEnd($quoteItem$cancellationPolicyFrontEnd);
  643.         $supplierCancellationPolicyFrontEnds = array();
  644.         $oxCancellationPolicyFrontEnds = array();
  645.         $this->setCancellationPolicyFrontEnds($quoteItem$request$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  646.         $myQuoteItem = new MyQuoteItemModel($quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  647.         $originalQuoteItem = clone $quoteItem;
  648.         $requestArray $request->request->all();
  649.         if (array_key_exists('my_quote_item'$requestArray) && array_key_exists('vendorId'$requestArray['my_quote_item']['quoteItem']) && !is_numeric($requestArray['my_quote_item']['quoteItem']['vendorId'])) {
  650.             unset($requestArray['my_quote_item']['quoteItem']['vendorId']);
  651.             $request->request->set('my_quote_item'$requestArray['my_quote_item']);
  652.         }
  653.         if ($parentQuoteItem $quoteItem->getParentQuoteItem()) {
  654.             $requestArray['my_quote_item']['quoteItem']['clientNameJson'] = $parentQuoteItem->getClientNameJson();
  655.             $requestArray['my_quote_item']['quoteItem']['clientLastNameJson'] = $parentQuoteItem->getClientLastNameJson();
  656.             $request->request->set('my_quote_item'$requestArray['my_quote_item']);
  657.         }
  658.         $isALaCarteAgent=false;
  659.         if($this->isGranted("ROLE_GET_COMMISSION_FROM_QUOTE_CUSTOMER_ACCOUNT")){
  660.             $isALaCarteAgent=true;
  661.             $options['isALaCarteAgent']=$isALaCarteAgent;
  662.             $options['canEditClientName']=false;
  663.             $options['canEditBeds']=false;
  664.             $options['canEditMealPlan']=false;
  665.             $options['canEditSpecialRequests']=false;
  666.         }
  667.         if(!in_array($quoteItem->getType(),[QuoteItem::PRODUCT_TYPE_TRANSFER,QuoteItem::PRODUCT_TYPE_CAR_RENTAL])&& ($quoteItem->isBooked() or $quoteItem->isCancelled())){
  668.             $options['canEditCheckInCheckOut']=false;
  669.         }
  670.         $options['canEditManuallyConfirmationNumber']=false;
  671.         if($quoteItem->canEditManuallyConfirmationNumber()){
  672.             $options['canEditManuallyConfirmationNumber']=true;
  673.         }
  674.         $options['canOverrideSupplier']=$quoteItem->canOverriteSupplier($this->getUser());
  675.         $form $this->createForm(MyQuoteItemType::class, $myQuoteItem$options);
  676.         $form->handleRequest($request);
  677.         try {
  678.             $quoteItem $myQuoteItem->getQuoteItem();
  679.             if($isALaCarteAgent){
  680.                 //This user just can edit Resort Fees
  681.                 if ($originalQuoteItem && ($originalQuoteItem->getResortFeesPaidOnSite() != $quoteItem->getResortFeesPaidOnSite())) {
  682.                     //Update just Resort Fees
  683.                     $em $this->getDoctrine()->getManager();
  684.                     $quoteItem->setResortFeesPaidOnSite($quoteItem->getResortFeesPaidOnSite());
  685.                     $em->persist($quoteItem);
  686.                     $em->flush();
  687.                     $this->addFlash('success''Resort Fees has been updated');
  688.                     return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  689.                 }
  690.             }
  691.             else {
  692.                 if ($quoteItem->getAdditionalInformation()) {
  693.                     if (isset($quoteItem->getAdditionalInformation()['pickupTime']) && is_array($quoteItem->getAdditionalInformation()['pickupTime'])) {
  694.                         $newDateTime = new \DateTime();
  695.                         $quoteItem->setAdditionalInformation(['pickupTime' => null]);
  696.                     }
  697.                 }
  698.                 if ($quoteItem->getAdditionalInformation()) {
  699.                     if (isset($quoteItem->getAdditionalInformation()['dropoffTime']) && is_array($quoteItem->getAdditionalInformation()['dropoffTime'])) {
  700.                         $newDateTime = new \DateTime();
  701.                         $quoteItem->setAdditionalInformation(['dropoffTime' => null]);
  702.                     }
  703.                 }
  704.                 $this->saveQuoteItem($request$form$quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds$originalQuoteItem'updated'$quickbooksAPI$reservationFactory$notificationSystem$coreApi$hubSpotAPI$reservationApi);
  705.                 if ($quoteItem->getAdditionalInformation()) {
  706.                     if (isset($quoteItem->getAdditionalInformation()['pickupTime']) && is_array($quoteItem->getAdditionalInformation()['pickupTime'])) {
  707.                         $newDateTime = new \DateTime();
  708.                         $quoteItem->setAdditionalInformation(['pickupTime' => null]);
  709.                     }
  710.                 }
  711.                 if ($quoteItem->getAdditionalInformation()) {
  712.                     if (isset($quoteItem->getAdditionalInformation()['dropoffTime']) && is_array($quoteItem->getAdditionalInformation()['dropoffTime'])) {
  713.                         $newDateTime = new \DateTime();
  714.                         $quoteItem->setAdditionalInformation(['dropoffTime' => null]);
  715.                     }
  716.                 }
  717.                 if (array_key_exists('my_quote_item'$requestArray) && array_key_exists('vendorId'$requestArray['my_quote_item']['quoteItem']) && !is_numeric($requestArray['my_quote_item']['quoteItem']['vendorId'])) {
  718.                     unset($requestArray['my_quote_item']['quoteItem']['vendorId']);
  719.                     $request->request->set('my_quote_item'$requestArray['my_quote_item']);
  720.                 }
  721.                 if ($parentQuoteItem $quoteItem->getParentQuoteItem()) {
  722.                     $requestArray['my_quote_item']['quoteItem']['clientNameJson'] = $parentQuoteItem->getClientNameJson();
  723.                     $requestArray['my_quote_item']['quoteItem']['clientLastNameJson'] = $parentQuoteItem->getClientLastNameJson();
  724.                     $request->request->set('my_quote_item'$requestArray['my_quote_item']);
  725.                 }
  726.                 $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  727.                 $this->setCancellationPolicyFrontEnd($quoteItem$cancellationPolicyFrontEnd);
  728.                 $supplierCancellationPolicyFrontEnds = array();
  729.                 $oxCancellationPolicyFrontEnds = array();
  730.                 $this->setCancellationPolicyFrontEnds($quoteItem$request$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  731.                 $myQuoteItem = new MyQuoteItemModel($quoteItem$cancellationPolicyFrontEnd$supplierCancellationPolicyFrontEnds$oxCancellationPolicyFrontEnds);
  732.                 $form $this->createForm(MyQuoteItemType::class, $myQuoteItem$options);
  733.                 $form->handleRequest($request);
  734.                 if ($quoteItem->isHotel()) {
  735.                     //Get Hotel Info
  736.                     $quoteItem->setHotelInfo($coreApi->getHotelInfoByIdProduct($quoteItem->getIdProduct()));
  737.                     $quoteItem->getQuote()->refreshQuoteDates();
  738.                 }
  739.             }
  740.         } catch (\Exception $e) {
  741.             $this->addFlash('error'"<p>The Quote Item couldn't be saved.</p><p></p> Error&colon; <br/>" $e->getMessage() . "</p>");
  742.             //try to preserve any new rate data
  743.             $data $request->request->all();
  744.             if (key_exists('ratesDetail'$data)) {
  745.                 $netRateDetail $quoteItem->getNetRateDetail();
  746.                 $requestRateData $data['ratesDetail'];
  747.                 if (is_array($requestRateData) && count($requestRateData) > 0) {
  748.                     foreach ($netRateDetail as $keyDate => &$netDetailRow) {
  749.                         if (isset($requestRateData[$keyDate])) {
  750.                             $netDetailRow['fee'] = $requestRateData[$keyDate]['netRateDetailFee'] ?? 0;
  751.                             $netDetailRow['price'] = $requestRateData[$keyDate]['netRateDetailPrice'] ?? 0;
  752.                             $netDetailRow['taxPercentage'] = $requestRateData['netTax'] ?? 0;
  753.                             $netDetailRow['comPercentage'] = $requestRateData['netRateDetailNetComTotal'] ?? 0;
  754.                         }
  755.                     }
  756.                 }
  757.                 $quoteItem->setNetRateDetail($netRateDetail); //just for display... no need to persist
  758.             }
  759.         }
  760.         $activitySuppliers $coreApi->getActivitySupplierList();
  761.         $em $this->getDoctrine()->getManager();
  762.         $exchangeRateData $em->getRepository(Currency::class)->getRatesByShortName();
  763.         $supplier = new Supplier();
  764.         $formSupplier $this->createForm(SupplierType::class, $supplier);
  765.         $formSupplier->handleRequest($request);
  766.         $quoteItem->setCoreApi($coreApi);//Init var
  767.         self::ClearBadFiles($form);
  768.         if($isALaCarteAgent){
  769.             return $this->render('backOffice/myQuote/show/show.html.twig', [
  770.                 'formMyQuoteItem' => $form->createView(),
  771.                 'quoteItem' => $quoteItem,
  772.                 'supplier' => $supplier,
  773.                 'formSupplier' => $formSupplier->createView(),
  774.                 'activitySuppliers' => $activitySuppliers,
  775.                 'exchangeRateData' => $exchangeRateData,
  776.                 'em' => $em,
  777.                 'hasQuoteCommission' => !!$quoteItem->getQuote()->getCustomerAccountCommissionType(),
  778.             ]);
  779.         }
  780.         return $this->render('backOffice/myQuote/edit.html.twig', [
  781.             'formMyQuoteItem' => $form->createView(),
  782.             'quoteItem' => $quoteItem,
  783.             'supplier' => $supplier,
  784.             'formSupplier' => $formSupplier->createView(),
  785.             'activitySuppliers' => $activitySuppliers,
  786.             'exchangeRateData' => $exchangeRateData,
  787.             'em' => $em,
  788.             'hasQuoteCommission' => !!$quoteItem->getQuote()->getCustomerAccountCommissionType(),
  789.         ]);
  790.     }
  791.     /**
  792.      * @Route("/remove/{id}", name="my_quoteItem_remove", methods={"GET","POST"})
  793.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  794.      * @param Request $request
  795.      * @param QuoteItem|null $quoteItem
  796.      * @param HubSpotAPI $hubSpotAPI
  797.      * @return Response
  798.      */
  799.     public function removeQuoteItem(Request $requestHubSpotAPI $hubSpotAPIQuoteItem $quoteItem null): Response
  800.     {
  801.         try {
  802.             if (!$quoteItem) {
  803.                 throw new \Exception('There is not a quote item to be deleted.');
  804.             }
  805.             if (!$quoteItem->canBeDeleted()) {
  806.                 throw new \Exception("This quote item can't be deleted.");
  807.             }
  808.             $quote $quoteItem->getQuote();
  809.             $em $this->getDoctrine()->getManager();
  810.             if (count($quoteItem->getChildrenQuoteItems())) {
  811.                 foreach ($quoteItem->getChildrenQuoteItems() as $childQuoteItem) {
  812.                     $em->remove($childQuoteItem);
  813.                 }
  814.             }
  815.             $em->remove($quoteItem);
  816.             $em->flush();
  817.             $quote->refreshQuoteReservationStatus();
  818.             $quote->refreshQuoteAccountingStatus();
  819.             $quote->refreshQuoteDates();
  820.             $em->flush();
  821.             if ($quote->getCustomerAccountCommissionType() == "usd") {
  822.                 $quoteItem->setCustomerAccountCommissionPercentage($quote->getCustomerAccountCommission());
  823.                 $em->flush();
  824.             }
  825.             $hubSpotAPI->deal($quote);
  826.             $this->addFlash('success''The Quote Item has been removed from the quote ' $quote->getTitle());
  827.         } catch (\Exception $e) {
  828.             if (isset($quoteItem)) {
  829.                 $this->addFlash('error'"The Quote Item couldn't be removed from the quote " $quoteItem->getQuote()->getTitle());
  830.             } else {
  831.                 $this->addFlash('error'$e->getMessage());
  832.             }
  833.         }
  834.         //Redirect to previous page
  835.         if ($url $request->headers->get('referer')) {
  836.             $url str_replace($request->getSchemeAndHttpHost(), ""$url);
  837.             return new RedirectResponse($url);
  838.         }
  839.         return $this->redirectToRoute('all_quotes_index');
  840.     }
  841.     /**
  842.      * @Route(path="/HideOrVisible/{quoteItem}", requirements={"quoteItem"="\d+"},name="my_quoteItem_hideOrVisible", methods={"POST"})
  843.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  844.      * @param HubSpotAPI $hubSpotAPI
  845.      * @param QuoteItem|null $quoteItem
  846.      * @return JsonResponse
  847.      */
  848.     public function setHideOrVisibleQuoteItem(HubSpotAPI $hubSpotAPIQuoteItem $quoteItem null): JsonResponse
  849.     {
  850.         try {
  851.             $em $this->getDoctrine()->getManager();
  852.             if(!$quoteItem->canBeHideOrVisible()){
  853.                 throw new \Exception($quoteItem->getMessageReasonCannotBeHideOrVisible());
  854.             }
  855.             $isHidden false;
  856.             if ($quoteItem->getIsHidden()) {
  857.                 $response = array(
  858.                     "status" => "visible"
  859.                 );
  860.             } else {
  861.                 $isHidden true;
  862.                 $response = array(
  863.                     "status" => "hide"
  864.                 );
  865.             }
  866.             $quoteItem->setIsHidden($isHidden);
  867.             $em->persist($quoteItem);
  868.             $em->flush();
  869.             $em->refresh($quoteItem);
  870.             $quote $quoteItem->getQuote();
  871.             $quote->refreshQuoteDates();
  872.             $em->persist($quote);
  873.             $em->flush();
  874.             $em->refresh($quote);
  875.             if ($quote->getCustomerAccountCommissionType() == "usd") {
  876.                 $quoteItem->setCustomerAccountCommissionPercentage($quote->getCustomerAccountCommission());
  877.             }
  878.             $em->flush();
  879.             $startDate $quote->getStartDate();
  880.             $startDate $startDate != null $startDate->format('Y-m-d') : "";
  881.             $response['startDate'] = $startDate;
  882.             $endDate $quote->getEndDate();
  883.             $endDate $endDate != null $endDate->format('Y-m-d') : "";
  884.             $response['endDate'] = $endDate;
  885.             $response['messageReasonCannotBeHideOrVisible'] = $quoteItem->getMessageReasonCannotBeHideOrVisible();
  886.             $hubSpotAPI->deal($quote);
  887.             return $this->json($response200);
  888.         } catch (\Exception $e) {
  889.             return $this->json(['error' => $e->getMessage()], 400);
  890.         }
  891.     }
  892.     private function setOrHideVisibility(HubSpotAPI $hubSpotAPIQuoteItem $quoteItem null$isHidden false): array
  893.     {
  894.         $em $this->getDoctrine()->getManager();
  895.         $response = array(
  896.             "status" => "visible"
  897.         );
  898.         if ($isHidden) {
  899.             $response = array(
  900.                 "status" => "hide"
  901.             );
  902.         }
  903.         $quoteItem->setIsHidden($isHidden);
  904.         $em->persist($quoteItem);
  905.         $em->flush();
  906.         $em->refresh($quoteItem);
  907.         $quote $quoteItem->getQuote();
  908.         $quote->refreshQuoteDates();
  909.         $em->persist($quote);
  910.         $em->flush();
  911.         $em->refresh($quote);
  912.         if($quote->getCustomerAccountCommissionType() == "usd"){
  913.             $quoteItem->setCustomerAccountCommissionPercentage($quote->getCustomerAccountCommission());
  914.         }
  915.         $em->flush();
  916.         $startDate $quote->getStartDate();
  917.         $startDate $startDate != null $startDate->format('Y-m-d'):"";
  918.         $response['startDate'] = $startDate;
  919.         $endDate $quote->getEndDate();
  920.         $endDate $endDate != null $endDate->format('Y-m-d'):"";
  921.         $response['endDate'] = $endDate;
  922.         $hubSpotAPI->deal($quote);
  923.         return $response;
  924.     }
  925.     /**
  926.      * @Route(path="/HideOrVisible/all", name="quote_set_hide_or_show_visibility", methods={"POST"})
  927.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  928.      * @param Request $request
  929.      * @param HubSpotAPI $hubSpotAPI
  930.      * @param QuoteRepository $quoteRepository
  931.      * @param QuoteItemRepository $quoteItemRepository
  932.      * @return Response
  933.      */
  934.     public function setHideOrVisibleBatchQuoteItem(Request $requestHubSpotAPI $hubSpotAPIQuoteRepository $quoteRepositoryQuoteItemRepository $quoteItemRepository): Response
  935.     {
  936.         try {
  937.             if (!$quote $quoteRepository->find($request->request->get('idQuote'))) {
  938.                 throw new \Exception("Quote is not valid.");
  939.             }
  940.             $quoteItems $request->request->get('quoteItems') ?? [];
  941.             foreach ($quote->getQuoteItems() as $quoteItem) {
  942.                 if (in_array($quoteItem->getId(), (array)$quoteItems)) {
  943.                     $quoteItem $quoteItemRepository->find($quoteItem->getId());
  944.                     $this->setOrHideVisibility($hubSpotAPI$quoteItem);
  945.                 } else {
  946.                     $this->setOrHideVisibility($hubSpotAPI$quoteItemtrue);
  947.                 }
  948.             }
  949.             $msg 'Your Quote Items have been change visibility';
  950.             $this->addFlash('success'$msg);
  951.         } catch (\Exception $e) {
  952.             $this->addFlash('error'$e->getMessage());
  953.         }
  954.         if (isset($quote)) {
  955.             return $this->redirectToRoute('quote_edit', array('id' => $quote->getId()));
  956.         }
  957.         return $this->redirectToRoute('all_quotes_index');
  958.     }
  959.     /**
  960.      * @param Request $request
  961.      * @param FormInterface $form
  962.      * @param QuoteItem $quoteItem
  963.      * @param CancellationPolicyModel|null $cancellationPolicyFrontEnd
  964.      * @param QuoteItem|null $originalQuoteItem
  965.      * @param string $actionString
  966.      * @param QuickbooksAPI|null $quickbooksAPI
  967.      * @param HubSpotAPI $hubSpotAPI
  968.      * @return \Symfony\Component\HttpFoundation\RedirectResponse|void
  969.      */
  970.     private function saveQuoteItem(Request $requestFormInterface $formQuoteItem &$quoteItemCancellationPolicyModel $cancellationPolicyFrontEnd null, array $supplierCancellationPolicyFrontEnds = [], array $oxCancellationPolicyFrontEnds = [], $originalQuoteItem null$actionString 'updated'QuickbooksAPI $quickbooksAPI nullReservationFactory $reservationFactory nullNotificationSystem $notificationSystem nullCoreApi $coreApi nullHubSpotAPI $hubSpotAPIReservationApi $reservationApi)
  971.     {
  972.         try {
  973.             if ($form->isSubmitted()) {
  974.                 if (!$form->isValid()) {
  975.                     /**
  976.                      * @var FormErrorIterator $formErrors
  977.                      * @var ConstraintViolation $cause
  978.                      */
  979.                     $formErrors $form->getErrors(true);
  980.                     $errors $formErrors->getChildren();
  981.                     throw new \Exception($errors->getMessage());
  982.                 }
  983.                 $refreshQuoteStatus=false;
  984.                 /**
  985.                  * @var $file UploadedFile
  986.                  */
  987.                 if ($file $form->get('attachFile')->getData()) {
  988.                     //Save the file
  989.                     if (!$newFilename $form->get('nameFile')->getData()) {
  990.                         $newFilename str_replace("." $file->guessClientExtension(), ""$file->getClientOriginalName());
  991.                     }
  992.                     //test for valid file
  993.                     $validFileTypes = array(
  994.                         'image/ief',
  995.                         'image/bmp',
  996.                         'image/png',
  997.                         'image/jpeg',
  998.                         'image/tiff',
  999.                         'application/pdf',
  1000.                         'application/x-pdf',
  1001.                         'text/csv',
  1002.                         'text/plain',
  1003.                         'application/msword',
  1004.                         'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  1005.                         'application/vnd.ms-excel',
  1006.                         'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  1007.                     $validFileExtension = array(
  1008.                         'jpg',
  1009.                         'jpeg',
  1010.                         'png',
  1011.                         'bmp',
  1012.                         'tiff',
  1013.                         'pdf',
  1014.                         'txt',
  1015.                         'csv'
  1016.                     );
  1017.                     $finfo finfo_open(FILEINFO_MIME_TYPE);
  1018.                     $type finfo_file($finfo$file);
  1019.                     if (!in_array($type$validFileTypes)) {
  1020.                         throw new \Exception("Invalid file type");
  1021.                     }
  1022.                     if (!in_array($file->guessClientExtension(), $validFileExtension)) {
  1023.                         throw new \Exception("Invalid file type");
  1024.                     }
  1025.                     ///
  1026.                     $newFilename str_replace("#"""$newFilename);
  1027.                     $newFilename preg_replace("/\s+/"""$newFilename);
  1028.                     $newFilename $newFilename "_" random_int(1000PHP_INT_MAX) . '.' $file->guessClientExtension();
  1029.                     $file->move(
  1030.                         $this->getParameter('quote_item_file_directory'),
  1031.                         $newFilename
  1032.                     );
  1033.                     //Save the file name
  1034.                     $quoteItem->addFile($newFilename);
  1035.                 }
  1036.                 if ($quoteItem->isTransfer()) {
  1037.                     if ($quoteItem->getAdditionalInformationTransferDate() != $originalQuoteItem->getAdditionalInformationTransferDate()) {
  1038.                         $quoteItem->setTransferDatesWithAdditionalInformation();
  1039.                     }
  1040.                     //Save the title from-to
  1041.                     $title[] = $quoteItem->getAdditionalInformationTransferPickupLocationName();
  1042.                     $title[] = $quoteItem->getAdditionalInformationTransferDropoffLocationName();
  1043.                     $quoteItem->setName(implode(" - "$title));
  1044.                 }
  1045.                 if ($quoteItem->isCarRental()) {
  1046.                     if ($quoteItem->getRentalCarPickupDateTimeWithAdditionalInformation() != $originalQuoteItem->getRentalCarPickupDateTimeWithAdditionalInformation() ||
  1047.                         $quoteItem->getRentalCarDropoffDateTimeWithAdditionalInformation() != $originalQuoteItem->getRentalCarPickupDateTimeWithAdditionalInformation()) {
  1048.                         $quoteItem->setRentalCarDatesWithAdditionalInformation();
  1049.                     }
  1050.                 }
  1051.                 if ($quoteItem->getCheckIn() > $quoteItem->getCheckOut()) {
  1052.                     throw new \Exception("Check in date must be lower than check out date");
  1053.                 }
  1054.                 if ($cancellationPolicyFrontEnd) {
  1055.                     if ($quoteItem->getCheckIn()) {
  1056.                         $penaltyDate null;
  1057.                         if (!is_null($cancellationPolicyFrontEnd->getD()) && $cancellationPolicyFrontEnd->getD() !== null) {
  1058.                             // days and time
  1059.                             $penaltyDateStr $quoteItem->getCheckIn()->format('Y-m-d');
  1060.                             if ($cancellationPolicyFrontEnd->getH() === null) {
  1061.                                 //Get time from check in ,if there is no select it
  1062.                                 $penaltyDateStr $quoteItem->getCheckIn()->format('Y-m-d\TH:i:s\Z');
  1063.                             } else {
  1064.                                 $penaltyDateStr .= 'T' $cancellationPolicyFrontEnd->getH() . ':00Z';
  1065.                             }
  1066.                             $penaltyDate = new \DateTime($penaltyDateStr);
  1067.                             $penaltyDate->sub(new \DateInterval("P" $cancellationPolicyFrontEnd->getD() . "D"));
  1068.                         }
  1069.                         $quoteItem->setCancellationPenaltyDate($penaltyDate);
  1070.                         $cancellationPolicy = array();
  1071.                         if ($penaltyDate) {
  1072.                             $penaltyStr "";
  1073.                             if ($cancellationPolicyFrontEnd->getPenalty() && $cancellationPolicyFrontEnd->getType()) {
  1074.                                 $penaltyStr $cancellationPolicyFrontEnd->getPenalty() . " " $cancellationPolicyFrontEnd->getType();
  1075.                             }
  1076.                             $cancellationPolicy $quoteItem->getCancellationPolicy();
  1077.                             if(!array_key_exists("0",$cancellationPolicy)){
  1078.                                 $cancellationPolicy['id'] = 'manual';
  1079.                                 $cancellationPolicy['name'] = $penaltyStr;
  1080.                                 $cancellationPolicy['type'] = $cancellationPolicyFrontEnd->getType();
  1081.                                 $cancellationPolicy['penalty'] = $cancellationPolicyFrontEnd->getPenalty();
  1082.                                 $cancellationPolicy['description'] = $penaltyStr;
  1083.                                 $cancellationPolicy['penaltyDate'] = $penaltyDate->format(\DATE_W3C);
  1084.                             } else { //clean up junk
  1085.                                 $tempPolicy = [];
  1086.                                 foreach($cancellationPolicy as $key => $row){
  1087.                                     if(is_numeric($key)){
  1088.                                         $tempPolicy[$key] = $row;
  1089.                                     }
  1090.                                 }
  1091.                                 $cancellationPolicy $tempPolicy;
  1092.                             }
  1093.                         }
  1094.                         if($quoteItem->canCancellationPolicyBeUpdated()){
  1095.                             $quoteItem->setCancellationPolicy($cancellationPolicy);
  1096.                         }
  1097.                         //setting the children
  1098.                         $childQuoteItem $quoteItem->getChildrenQuoteItems();
  1099.                         foreach ($childQuoteItem as $childQuoteItem) {
  1100.                             if (in_array($childQuoteItem->getType(), ['resortFee''hotel_service'])) {
  1101.                                 $childQuoteItem->setCancellationPolicy($cancellationPolicy);
  1102.                             }
  1103.                         }
  1104.                     }
  1105.                 }
  1106.                 if (count($supplierCancellationPolicyFrontEnds) > && $quoteItem->canCancellationPolicyBeUpdated()) {
  1107.                     $supplierCancellationPolicies = array();
  1108.                     foreach ($supplierCancellationPolicyFrontEnds as $supplierCancellationPolicyFrontEnd) {
  1109.                         if ($supplierCancellationPolicyFrontEnd && $quoteItem->getCheckIn()) {
  1110.                             $penaltyDate null;
  1111.                             if (!is_null($supplierCancellationPolicyFrontEnd->getD()) && $supplierCancellationPolicyFrontEnd->getD() !== null) {
  1112.                                 // days and time
  1113.                                 $penaltyDateStr $quoteItem->getCheckIn()->format('Y-m-d');
  1114.                                 if ($supplierCancellationPolicyFrontEnd->getH() === null) {
  1115.                                     //Get time from check in ,if there is no select it
  1116.                                     $penaltyDateStr $quoteItem->getCheckIn()->format('Y-m-d\TH:i:s\Z');
  1117.                                 } else {
  1118.                                     $penaltyDateStr .= 'T' $supplierCancellationPolicyFrontEnd->getH() . ':00Z';
  1119.                                 }
  1120.                                 $penaltyDate = new \DateTime($penaltyDateStr);
  1121.                                 $penaltyDate->sub(new \DateInterval("P" $supplierCancellationPolicyFrontEnd->getD() . "D"));
  1122.                             }
  1123.                             $cancellationPolicy = array();
  1124.                             if ($penaltyDate) {
  1125.                                 $penaltyStr "";
  1126.                                 if ($supplierCancellationPolicyFrontEnd->getPenalty() && $supplierCancellationPolicyFrontEnd->getType()) {
  1127.                                     $penaltyStr $supplierCancellationPolicyFrontEnd->getPenalty() . " " $supplierCancellationPolicyFrontEnd->getType();
  1128.                                 }
  1129.                                 $cancellationPolicy $quoteItem->getCancellationPolicy();
  1130.                                 $cancellationPolicy['id'] = 'manual';
  1131.                                 $cancellationPolicy['name'] = $penaltyStr;
  1132.                                 $cancellationPolicy['type'] = $supplierCancellationPolicyFrontEnd->getType();
  1133.                                 $cancellationPolicy['penalty'] = $supplierCancellationPolicyFrontEnd->getPenalty();
  1134.                                 $cancellationPolicy['description'] = $penaltyStr;
  1135.                                 $cancellationPolicy['penaltyDate'] = $penaltyDate->format(\DATE_W3C);
  1136.                             }
  1137.                             $supplierCancellationPolicies[] = $cancellationPolicy;
  1138.                         }
  1139.                     }
  1140.                     $quoteItem->setCancellationPolicySupplier($supplierCancellationPolicies);
  1141.                     //setting the children
  1142.                     $childQuoteItems $quoteItem->getChildrenQuoteItems();
  1143.                     foreach ($childQuoteItems as $childQuoteItem) {
  1144.                         if (in_array($childQuoteItem->getType(), ['resortFee''hotel_service'])) {
  1145.                             $childQuoteItem->setCancellationPolicySupplier($supplierCancellationPolicies);
  1146.                             $childQuoteItem->setUseOxCancellationPolicy($quoteItem->getUseOxCancellationPolicy() ?? false);
  1147.                         }
  1148.                     }
  1149.                 }
  1150.                 if (count($oxCancellationPolicyFrontEnds) > 0) {
  1151.                     $oxCancellationPolicies = array();
  1152.                     foreach ($oxCancellationPolicyFrontEnds as $oxCancellationPolicyFrontEnd) {
  1153.                         if ($oxCancellationPolicyFrontEnd && $quoteItem->getCheckIn()) {
  1154.                             $penaltyDate null;
  1155.                             if (!is_null($oxCancellationPolicyFrontEnd->getD()) && $oxCancellationPolicyFrontEnd->getD() !== null) {
  1156.                                 // days and time
  1157.                                 $penaltyDateStr $quoteItem->getCheckIn()->format('Y-m-d');
  1158.                                 if ($oxCancellationPolicyFrontEnd->getH() === null) {
  1159.                                     //Get time from check in ,if there is no select it
  1160.                                     $penaltyDateStr $quoteItem->getCheckIn()->format('Y-m-d\TH:i:s\Z');
  1161.                                 } else {
  1162.                                     $penaltyDateStr .= 'T' $oxCancellationPolicyFrontEnd->getH() . ':00Z';
  1163.                                 }
  1164.                                 $penaltyDate = new \DateTime($penaltyDateStr);
  1165.                                 $penaltyDate->sub(new \DateInterval("P" $oxCancellationPolicyFrontEnd->getD() . "D"));
  1166.                             }
  1167.                             $cancellationPolicy = array();
  1168.                             if ($penaltyDate) {
  1169.                                 $penaltyStr "";
  1170.                                 if ($oxCancellationPolicyFrontEnd->getPenalty() && $oxCancellationPolicyFrontEnd->getType()) {
  1171.                                     $penaltyStr $oxCancellationPolicyFrontEnd->getPenalty() . " " $oxCancellationPolicyFrontEnd->getType();
  1172.                                 }
  1173.                                 $cancellationPolicy $quoteItem->getCancellationPolicy();
  1174.                                 $cancellationPolicy['id'] = 'manual';
  1175.                                 $cancellationPolicy['name'] = $penaltyStr;
  1176.                                 $cancellationPolicy['type'] = $oxCancellationPolicyFrontEnd->getType();
  1177.                                 $cancellationPolicy['penalty'] = $oxCancellationPolicyFrontEnd->getPenalty();
  1178.                                 $cancellationPolicy['description'] = $penaltyStr;
  1179.                                 $cancellationPolicy['penaltyDate'] = $penaltyDate->format(\DATE_W3C);
  1180.                             }
  1181.                             $oxCancellationPolicies[] = $cancellationPolicy;
  1182.                         }
  1183.                     }
  1184.                     $quoteItem->setCancellationPolicyOx($oxCancellationPolicies);
  1185.                     //setting the children
  1186.                     $childQuoteItems $quoteItem->getChildrenQuoteItems();
  1187.                     foreach ($childQuoteItems as $childQuoteItem) {
  1188.                         if (in_array($childQuoteItem->getType(), ['resortFee''hotel_service'])) {
  1189.                             $childQuoteItem->setCancellationPolicyOx($oxCancellationPolicies);
  1190.                             $childQuoteItem->setUseOxCancellationPolicy($quoteItem->getUseOxCancellationPolicy() ?? false);
  1191.                         }
  1192.                     }
  1193.                 }
  1194.                 $quoteItem->setCancellationPenaltyDate($quoteItem->getCancellationPolicyDate());
  1195.                 if($originalQuoteItem) {
  1196.                     if ($originalQuoteItem->getCancellationPolicy() != $quoteItem->getCancellationPolicy()) {
  1197.                         //todo BAV handle if manually entered supplier policy
  1198.                         //The cancellation policy was edited.
  1199.                         $quoteItem->setCancellationPolicyIsCustomized(true);
  1200.                     }
  1201.                     //If the supplier was changed, and the Quote Item was already invoiced, we have to make sure to cancel the bill in QBO
  1202.                     // for the original supplier and create a new bill for the new supplier.
  1203.                     if ($originalQuoteItem->requiresASupplier()) {
  1204.                         if ($originalQuoteItem->getVendorId() && ($originalQuoteItem->getVendorId() != $quoteItem->getVendorId())) {
  1205.                             //Supplies changes...
  1206.                             if (!$originalQuoteItem->canOverriteSupplier($this->getUser())) {
  1207.                                 throw new \Exception("Supplier cannot be changed.");
  1208.                             }
  1209.                             //If the supplier was changed, and the Quote Item was already invoiced, we have to make sure to cancel the bill in QBO
  1210.                             // for the original supplier and create a new bill for the new supplier.
  1211.                             $quickbooksAPI->updateSupplier($quoteItem$coreApi);
  1212.                         }
  1213.                     }
  1214.                     if ($originalQuoteItem && ($originalQuoteItem->getConfirmationNumber() != $quoteItem->getConfirmationNumber())
  1215.                         && $quoteItem->getConfirmationNumber()) {
  1216.                         if($quoteItem->isRefused()){
  1217.                             //Confirmation number cannot be added to a refused quote item
  1218.                             throw new \Exception("This quote item has status REFUSED, confirmation number cannot be added.");
  1219.                         }
  1220.                         if ($quoteItem->canBeManuallyUpdatedConfNumberAndBook()) {
  1221.                             if ($quoteItem->getSource() == QuoteItem::PRODUCT_SOURCE_STATIC) {
  1222.                                 if (empty($quoteItem->getApiReservationId())) {
  1223.                                     $confNo $quoteItem->getConfirmationNumber();
  1224.                                     $reservationFactory->bookRequest($notificationSystem$coreApi$quoteItem$this->generateUrl('quote_edit', array('id' => $quoteItem->getQuote()->getId())), true);
  1225.                                     //The bookRequest process clears out the conf # so we need to set it back
  1226.                                     $quoteItem->setConfirmationNumber($confNo);
  1227.                                 }
  1228.                                 $reservation $reservationApi->getReservationById($quoteItem->getApiReservationId());
  1229.                                 $reservationToken $reservation['reservations'][0]['reservationNumber'] ?? "";
  1230.                                 if ($reservationToken != "") {
  1231.                                     $reservationApi->setReservationConfirmationNumber($reservationToken$quoteItem->getApiReservationId(), $quoteItem->getConfirmationNumber());
  1232.                                 }
  1233.                                 $quoteItem->setReservationStatus(QuoteItem::RESERVATION_STATUS_BOOK);
  1234.                                 $refreshQuoteStatus true;
  1235.                             } else {
  1236.                                 $reservationFactory->bookRequest($notificationSystem$coreApi$quoteItem$this->generateUrl('quote_edit', array('id' => $quoteItem->getQuote()->getId())), true);
  1237.                             }
  1238.                             $this->addFlash('success'"Confirmation Number was updated. Reservation status changed to Booked");
  1239.                         }
  1240. //                    else{
  1241. //                        $quoteItem->setConfirmationNumber($originalQuoteItem->getConfirmationNumber());
  1242. //                        $this->addFlash('warning', "Confirmation Number cannot be updated.");
  1243. //                    }
  1244.                     }
  1245.                 }
  1246.                 $data $request->request->all();
  1247.                 if (!array_key_exists("my_quote_item"$data)) { //$data['my_quote_item']["quoteItem"]["checkIn"]
  1248.                     $data["my_quote_item"] = array();
  1249.                 }
  1250.                 if (!array_key_exists("quoteItem"$data["my_quote_item"])) { //$data['my_quote_item']["quoteItem"]["checkIn"]
  1251.                     $data["my_quote_item"]["quoteItem"] = array();
  1252.                 }
  1253.                 if (empty($data['my_quote_item']["quoteItem"]["checkIn"])) {
  1254.                     $data['my_quote_item']["quoteItem"]["checkIn"] = $quoteItem->getCheckInString();
  1255.                 }
  1256.                 if (empty($data['my_quote_item']["quoteItem"]["checkOut"])) {
  1257.                     $data['my_quote_item']["quoteItem"]["checkOut"] = $quoteItem->getCheckOutString();
  1258.                 }
  1259.                 $quoteItem->setUseOxCancellationPolicy($data['my_quote_item']["useOxCancellationPolicy"] ?? false);
  1260. //                if($quoteItem->getType()==QuoteItem::PRODUCT_TYPE_ACTIVITY){
  1261. //                    $quoteItem->setAdditionalInformation(array("dateKey"=>$quoteItem->getCheckIn(),"priceType"=>array()));
  1262. //                }
  1263.                 $this->getCancellationPolicyLabel($quoteItem);
  1264.                 if (key_exists('my_quote_item'$data)) {
  1265.                     $dataMyQuoteItem $data['my_quote_item'];
  1266.                     if (key_exists('newVoucherAdditionalNotes'$dataMyQuoteItem) && $dataMyQuoteItem['newVoucherAdditionalNotes']) {
  1267.                         $quoteItem->addVoucherAdditionalNote($dataMyQuoteItem['newVoucherAdditionalNotes']);
  1268.                     }
  1269.                 }
  1270.                 if (in_array($quoteItem->getType(), [QuoteItem::PRODUCT_TYPE_HOTEL_RESORT_FEEQuoteItem::PRODUCT_TYPE_HOTEL_SERVICE])) {
  1271.                     $parentQuoteItem $this->getDoctrine()->getRepository(QuoteItem::class)->findOneBy(array('id' => $quoteItem->getParentQuoteItem()->getId()));
  1272.                     $quoteItem->setOriginalCurrency($parentQuoteItem->getOriginalCurrency());
  1273.                     $quoteItem->setDisplayInOriginalCurrency($parentQuoteItem->getDisplayInOriginalCurrency() ?? false);
  1274.                     $quoteItem->setExchangeRate($parentQuoteItem->getExchangeRate());
  1275.                 }
  1276.                 if (key_exists('ratesDetail'$data)) {
  1277.                     if ($data['ratesDetail']['customerAccountCommissionPercentage'] != $quoteItem->getCustomerAccountCommissionPercentage()) {
  1278.                         $quoteItem->setCustomerAccountCommissionPercentage($data['ratesDetail']['customerAccountCommissionPercentage']);
  1279.                     }
  1280.                     if (key_exists('ratesDetail'$data) and is_array($data['ratesDetail'])) {
  1281.                         //Transform string to float values and reset to USD if needed:
  1282.                         foreach ($data['ratesDetail'] as $key => $value) {
  1283.                             if (strpos($key'-') === false) {
  1284.                                 $data['ratesDetail'][$key] = $this->convertStrToFloat($value);
  1285.                                 if ($quoteItem->getDisplayInOriginalCurrency() && stripos($key'percent') === false && stripos($key'tax') === false && stripos($key'netRateDetailNetCom') === false) {
  1286.                                     $data['ratesDetail'][$key] = floatval($data['ratesDetail'][$key] / $quoteItem->getExchangeRate());
  1287.                                 }
  1288.                             } else {
  1289.                                 foreach ($data['ratesDetail'][$key] as $keyDate => $valueDate) {
  1290.                                     if (strpos($keyDate'-') === false) {
  1291.                                         $data['ratesDetail'][$key][$keyDate] = $this->convertStrToFloat($valueDate);
  1292.                                         if ($quoteItem->getDisplayInOriginalCurrency() && stripos($keyDate'percent') === false && stripos($keyDate'tax') === false && stripos($keyDate'netRateDetailNetCom') === false) {
  1293.                                             $data['ratesDetail'][$key][$keyDate] = floatval($data['ratesDetail'][$key][$keyDate] / $quoteItem->getExchangeRate());
  1294.                                         }
  1295.                                     }
  1296.                                 }
  1297.                                 $testDate \DateTime::createFromFormat('m-d-Y'$key);
  1298.                                 if ($testDate == null) {
  1299.                                     $testDate \DateTime::createFromFormat('d-m-Y'$key);
  1300.                                 }
  1301.                                 if ($testDate !== false) {
  1302.                                     $correctedDate $testDate->format('Y-m-d');
  1303.                                     $data['ratesDetail'][$correctedDate] = $data['ratesDetail'][$key];
  1304.                                     unset($data['ratesDetail'][$key]);
  1305.                                 }
  1306.                             }
  1307.                         }
  1308.                     }
  1309.                     $correctedRatesTable = [];
  1310.                     $currentRatesTable $quoteItem->getFullRateTableDetail() ?? [];
  1311.                     foreach ($currentRatesTable as $date => $row) {
  1312.                         $testDate \DateTime::createFromFormat('m-d-Y'$date);
  1313.                         if ($testDate == null) {
  1314.                             $testDate \DateTime::createFromFormat('d-m-Y'$date);
  1315.                         }
  1316.                         if ($testDate !== false) {
  1317.                             $correctedDate $testDate->format('Y-m-d');
  1318.                             $correctedRatesTable[$correctedDate] = $row;
  1319.                         } else {
  1320.                             $correctedRatesTable[$date] = $row;
  1321.                         }
  1322.                     }
  1323.                     if (count($correctedRatesTable) > 0) {
  1324.                         $quoteItem->setFullRateTableDetail($correctedRatesTable);
  1325.                     }
  1326.                     $updatedRates false;
  1327.                     //Check the rates
  1328.                     if ($quoteItem->canRatesBeUpdated()) { //Net rates cannot be edited when the source is dynamic
  1329.                         $netRateDetail in_array($quoteItem->getType(), [QuoteItem::PRODUCT_TYPE_ACTIVITYQuoteItem::PRODUCT_TYPE_VILLA]) ? false $quoteItem->getNetRateDetail();
  1330.                         if ((in_array($quoteItem->getType(), [QuoteItem::PRODUCT_TYPE_HOTEL_SERVICEQuoteItem::PRODUCT_TYPE_TRANSFERQuoteItem::PRODUCT_TYPE_CAR_RENTAL])) && !empty($netRateDetail) && self::adjustRateDates($netRateDetail$quoteItem->getCheckInAsDate(), $quoteItem->getCheckOutAsDate(), $request->request->all(), 'net')) {
  1331.                             $quoteItem->setNetRateDetail($netRateDetail);
  1332.                         }
  1333.                         $netRateDetailNetComKey key_exists('netRateDetailNetComTotal'$data['ratesDetail']) ? 'netRateDetailNetComTotal' 'netRateDetailNetCom';
  1334.                         if ($this->updateCustomRatesDetail($netRateDetail$data'netTax''netRateDetailPrice''netRateDetailFee'1$netRateDetailNetComKey)) {
  1335.                             $updatedRates true;
  1336.                             $quoteItem->setNetIsCustomized(true);
  1337.                             $quoteItem->setNetRateDetail($netRateDetail);
  1338.                             //Net Prices
  1339.                             $quoteItem->setNetTaxPercentage($data['ratesDetail']['netTax']);
  1340.                             $quoteItem->setNetBeforeTax($data['ratesDetail']['netRateDetailPriceTotal']);
  1341.                             $quoteItem->setNetTax($data['ratesDetail']['netTax'] * $quoteItem->getNetBeforeTax() / 100); //CHECK THIS VALUE
  1342.                             $quoteItem->setNetFee($data['ratesDetail']['netRateDetailFeeTotal']);
  1343.                             $quoteItem->setNetTotal($quoteItem->getNetTax() + $quoteItem->getNetFee() + $quoteItem->getNetBeforeTax()); //CHECK THIS VALUE
  1344.                             //$quoteItem->setNetAdditionalBeforeTax(0);
  1345.                         }
  1346.                         if ($quoteItem->getNetTotal() != $originalQuoteItem->getNetTotal() && $quoteItem->getQuickbookPayableReferenceId() && $quickbooksAPI) {
  1347.                             if ($parentQuoteItem $quoteItem->getParentQuoteItem()) {
  1348.                                 $quickbooksAPI->qbPayable($parentQuoteItem);
  1349.                             }else{
  1350.                                 $quickbooksAPI->qbPayable($quoteItem);
  1351.                             }
  1352.                         }
  1353.                     }
  1354.                     $customerAccountCommissionPercentage abs($data['ratesDetail']['customerAccountCommissionPercentage']);
  1355.                     $commissionRateDetail in_array($quoteItem->getType(), [QuoteItem::PRODUCT_TYPE_ACTIVITYQuoteItem::PRODUCT_TYPE_VILLA]) ? false $quoteItem->getCommissionRateDetail();
  1356.                     if ((in_array($quoteItem->getType(), [QuoteItem::PRODUCT_TYPE_HOTEL_SERVICEQuoteItem::PRODUCT_TYPE_TRANSFERQuoteItem::PRODUCT_TYPE_CAR_RENTAL])) && !empty($commissionRateDetail) && self::adjustRateDates($commissionRateDetail$quoteItem->getCheckInAsDate(), $quoteItem->getCheckOutAsDate(), $request->request->all(), 'commission')) {
  1357.                         $quoteItem->setCommissionRateDetail($commissionRateDetail);
  1358.                     }
  1359.                     if ($customerAccountCommissionPercentage != $originalQuoteItem->getCustomerAccountCommissionPercentage() | ($this->updateCustomRatesDetail($commissionRateDetail$data'retailTax''retailRateDetailPrice''retailRateDetailFee'))) {
  1360.                         $updatedRates true;
  1361.                         if (!$commissionRateDetail) {
  1362.                             $this->updateCustomRatesDetail($commissionRateDetail$data'retailTax''retailRateDetailPrice''retailRateDetailFee');
  1363.                         }
  1364.                         $quoteItem->setRetailTaxPercentage($data['ratesDetail']['retailTax']);
  1365.                         //Commission Prices
  1366.                         $quoteItem->setCommissionIsCustomized(true);
  1367.                         $quoteItem->setCommissionRateDetail($commissionRateDetail ?? null);
  1368.                         $quoteItem->setCommissionFee($data['ratesDetail']['retailRateDetailFeeTotal']);
  1369.                         $quoteItem->setCommissionBeforeTax($data['ratesDetail']['retailRateDetailPriceTotal']);
  1370.                         $quoteItem->setCommissionTax($data['ratesDetail']['retailTax'] * $quoteItem->getCommissionBeforeTax() / 100);
  1371.                         $quoteItem->setCommissionTotal($quoteItem->getCommissionTax() + $quoteItem->getCommissionFee(false) + $quoteItem->getCommissionBeforeTax());
  1372.                         //Retail prices
  1373.                         $customerAccountCommissionPercentage abs($data['ratesDetail']['customerAccountCommissionPercentage']);
  1374.                         $quoteItem->setCustomerAccountCommissionPercentage($customerAccountCommissionPercentage);
  1375.                         if (!$customerAccountCommissionPercentage) {
  1376.                             $updatedRates true;
  1377.                             $quoteItem->setRetailIsCustomized(true);
  1378.                             $quoteItem->setRetailRateDetail($commissionRateDetail);
  1379.                             $quoteItem->setRetailFee($quoteItem->getCommissionFee(false));
  1380.                             $quoteItem->setRetailBeforeTax($quoteItem->getCommissionBeforeTax());
  1381.                             $quoteItem->setRetailTax($quoteItem->getCommissionTax());
  1382.                             $quoteItem->setRetailTotal($quoteItem->getCommissionTotal());
  1383.                         } else {
  1384.                             $retailRateDetail in_array($quoteItem->getType(), [QuoteItem::PRODUCT_TYPE_ACTIVITYQuoteItem::PRODUCT_TYPE_VILLA]) ? false $quoteItem->getRetailRateDetail();
  1385.                             if (($quoteItem->getType() == QuoteItem::PRODUCT_TYPE_HOTEL_SERVICE) && self::adjustRateDates($retailRateDetail$quoteItem->getCheckInAsDate(), $quoteItem->getCheckOutAsDate(), $request->request->all(), 'retail')) {
  1386.                                 $quoteItem->setRetailRateDetail($retailRateDetail);
  1387.                             }
  1388.                             $customerAccountCommissionFactor - ($customerAccountCommissionPercentage 100);
  1389.                             $this->updateCustomRatesDetail($retailRateDetail$data'retailTax''retailRateDetailPrice''retailRateDetailFee'$customerAccountCommissionFactor);
  1390.                             $quoteItem->setRetailRateDetail($retailRateDetail);
  1391.                             $quoteItem->setRetailFee($quoteItem->getCommissionFee(false));
  1392.                             $quoteItem->setRetailBeforeTax($quoteItem->getCommissionBeforeTax() * $customerAccountCommissionFactor);
  1393.                             $quoteItem->setRetailTax($quoteItem->getCommissionTax() * $customerAccountCommissionFactor);
  1394.                             $quoteItem->setRetailTotal($quoteItem->getRetailTax() + $quoteItem->getRetailFee() + $quoteItem->getRetailBeforeTax());
  1395.                         }
  1396.                     }
  1397.                     if ($quoteItem->isTransfer()) {
  1398.                         $quoteItem->setAdditionalInformationTransferVehicleRates();
  1399.                     }
  1400.                 }
  1401.                 if ((key_exists('showRatesInOneLine'$data))) {
  1402.                     $quoteItem->setShowRatesInOneLine($data['showRatesInOneLine']);
  1403.                 } else {
  1404.                     $quoteItem->setShowRatesInOneLine(false);
  1405.                 }
  1406.                 $em $this->getDoctrine()->getManager();
  1407.                 $em->persist($quoteItem);
  1408.                 //Refresh quote Start date and End date.
  1409.                 $quoteItem->getQuote()->refreshQuoteDates($quoteItem->getCheckInAsDate(), $quoteItem->getCheckOutAsDate());
  1410.                 $em->persist($quoteItem->getQuote());
  1411.                 $em->flush();
  1412.                 $em->refresh($quoteItem);
  1413.                 if ($originalQuoteItem &&
  1414.                     ($originalQuoteItem->getCheckIn() != $quoteItem->getCheckIn() || $originalQuoteItem->getCheckOut() != $quoteItem->getCheckOut())) {
  1415.                     $this->addFlash('success''The Quote dates has been updated');
  1416.                 }
  1417.                 if ($actionString == 'added' || $refreshQuoteStatus) {
  1418.                     //Refresh status
  1419.                     $quoteItem->getQuote()->refreshQuoteReservationStatus();
  1420.                     $quoteItem->getQuote()->refreshQuoteAccountingStatus();
  1421.                     $em->persist($quoteItem->getQuote());
  1422.                     $em->flush();
  1423.                     $em->refresh($quoteItem);
  1424.                     if($actionString == 'added'){
  1425.                         if ($quoteItemsSorted $em->getRepository(QuoteItem::class)->quoteItemsSorted($quoteItem->getQuote()->getId(), 'myQuotes')) {
  1426.                             if ($quoteItemsUpdate $quoteItem->getQuote()->refreshSortQuoteItemsByNewQuoteItem($quoteItem$quoteItemsSorted)) {
  1427.                                 foreach ($quoteItemsUpdate as $quoteItemUpdate) {
  1428.                                     $em->persist($quoteItemUpdate);
  1429.                                     $em->flush();
  1430.                                 }
  1431.                             }
  1432.                         }
  1433.                     }
  1434.                 }
  1435.                 if (count($quoteItem->getChildrenQuoteItems())) {
  1436.                     foreach ($quoteItem->getChildrenQuoteItems() as $childQuoteItem) {
  1437.                         $childQuoteItem->setClientNameJson($quoteItem->getClientNameJson())
  1438.                             ->setClientLastNameJson($quoteItem->getClientLastNameJson());
  1439.                         if (in_array($childQuoteItem->getType(), array(QuoteItem::PRODUCT_TYPE_HOTEL_RESORT_FEEQuoteItem::PRODUCT_TYPE_HOTEL_SERVICE))) {
  1440.                             //If the cancellation policy of the parent hotel is updated, we need to update the cancellation
  1441.                             // policy of the resort fee
  1442.                             $childQuoteItem->setCancellationPolicy($quoteItem->getCancellationPolicy());
  1443.                             $childQuoteItem->setCancellationPenaltyDate($quoteItem->getCancellationPenaltyDate());
  1444.                             $childQuoteItem->setCancellationPenaltyId($quoteItem->getCancellationPenaltyId());
  1445.                             $childQuoteItem->setCancellationPolicyLabel($quoteItem->getCancellationPolicyLabels());
  1446.                             $childQuoteItem->setUseOxCancellationPolicy($quoteItem->getUseOxCancellationPolicy());
  1447.                             $childQuoteItem->setCancellationPolicyOx($quoteItem->getCancellationPolicyOx());
  1448.                             $childQuoteItem->setCancellationPolicySupplier($quoteItem->getCancellationPolicySupplier());
  1449.                             $childQuoteItem->setOriginalCurrency($quoteItem->getOriginalCurrency());
  1450.                             $childQuoteItem->setDisplayInOriginalCurrency($quoteItem->getDisplayInOriginalCurrency() ?? false);
  1451.                             $childQuoteItem->setExchangeRate($quoteItem->getExchangeRate());
  1452.                         }
  1453.                         $em->persist($childQuoteItem);
  1454.                     }
  1455.                     $em->flush();
  1456.                 }
  1457.                 $billingSupplier $request->request->get('additionalInformation_billing_supplier') ?? null;
  1458.                 if ($billingSupplier != null && $quoteItem->getSource() == QuoteItem::PRODUCT_SOURCE_MANUALLY) {
  1459.                     $billingSupplier $billingSupplier $billingSupplier null;
  1460.                     $quoteItem->setAdditionalInformation(['billing_supplier' => $billingSupplier]);
  1461.                 }
  1462.                 $quote $quoteItem->getQuote();
  1463.                 $hubSpotAPI->deal($quote);
  1464.                 $this->addFlash('success''The Quote Item has been ' $actionString);
  1465.                 return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  1466.             }
  1467.         } catch (\Exception $e) {
  1468.             $this->addFlash('error'"<p>The Quote Item couldn't be saved.</p><p></p> Error&colon; <br/>" $e->getMessage() . "</p>");
  1469.             return $form;
  1470.         }
  1471.     }
  1472.     private function setCancellationPolicyFrontEnd(QuoteItem $quoteItem, &$cancellationPolicyFrontEnd)
  1473.     {
  1474.         if ($cancellationPolicyData $quoteItem->getCancellationPolicy()) {
  1475.             if (key_exists("penaltyDate"$cancellationPolicyData) && $cancellationPolicyData["penaltyDate"] && $quoteItem->getCheckIn()) {
  1476.                 //Get days and time
  1477.                 if(is_string($cancellationPolicyData["penaltyDate"])){
  1478.                     $cancellationPolicyData["penaltyDate"] = new \DateTime($cancellationPolicyData["penaltyDate"]);
  1479.                 }
  1480.                 $diff $quoteItem->getCheckInAsDate()->diff($cancellationPolicyData["penaltyDate"]);
  1481.                 if($quoteItem->getType() == QuoteItem::PRODUCT_TYPE_HOTEL && $diff->0){
  1482.                     $cancellationPolicyFrontEnd->setD($diff->days 1); //add one to account for the hours
  1483.                     $cancellationPolicyFrontEnd->setH(0);
  1484.                 } else {
  1485.                     $cancellationPolicyFrontEnd->setD($diff->days);
  1486.                     $cancellationPolicyFrontEnd->setH($diff->h);
  1487.                 }
  1488.                 $cancellationPolicyFrontEnd->setTz($cancellationPolicyData["penaltyDate"]->getTimeZone());
  1489.                 $cancellationPolicyFrontEnd->setPenalty($cancellationPolicyData['penalty']);
  1490.                 $cancellationPolicyFrontEnd->setType($cancellationPolicyData['type']);
  1491.             }
  1492.         }
  1493.     }
  1494.     private function setCancellationPolicyFrontEnds(QuoteItem $quoteItemRequest $request, &$supplierCancellationPolicyFrontEnds, &$oxCancellationPolicyFrontEnds)
  1495.     {
  1496.         $originalCancellationPolicies $quoteItem->getInitialCancellationPolicy();
  1497.         $supplierCancellationPolicies $quoteItem->getCancellationPolicySupplier();
  1498.         if(null != $supplierCancellationPolicies && array_key_exists('penaltyDate',$supplierCancellationPolicies)){ //make it an array of 1
  1499.             $tempCancellationPolicies = array($supplierCancellationPolicies);
  1500.             $supplierCancellationPolicies $tempCancellationPolicies;
  1501.         }
  1502.         $oxCancellationPolicies $quoteItem->getCancellationPolicyOx();
  1503.         if(null != $oxCancellationPolicies && array_key_exists('penaltyDate',$oxCancellationPolicies)){ //make it an array of 1
  1504.             $tempCancellationPolicies = array($oxCancellationPolicies);
  1505.             $oxCancellationPolicies $tempCancellationPolicies;
  1506.         }
  1507.         foreach($supplierCancellationPolicies as $index => $supplierCancellationPolicy){
  1508.             if($cancellationPolicyData $supplierCancellationPolicy){
  1509.                 $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  1510.                 if(key_exists("penaltyDate"$cancellationPolicyData) && $cancellationPolicyData["penaltyDate"] && $quoteItem->getCheckIn()){
  1511.                     //Get days and time
  1512.                     if(is_string($cancellationPolicyData["penaltyDate"])){
  1513.                         try{
  1514.                             $penaltyDate date_create_from_format(\DATE_W3C$cancellationPolicyData["penaltyDate"]);
  1515.                             if (!$penaltyDate) {
  1516.                                 $penaltyDate date_create_from_format('Y-m-d H:i:s'$cancellationPolicyData["penaltyDate"]);
  1517.                                 //new \DateTime($cancellationPolicyData["penaltyDate"]);
  1518.                             }
  1519.                             $cancellationPolicyData["penaltyDate"] = $penaltyDate;
  1520.                         }catch(\Exception $e){
  1521.                         }
  1522.                     }
  1523.                     if(is_array($cancellationPolicyData["penaltyDate"])){
  1524.                         try{
  1525.                             $cancellationPolicyData["penaltyDate"] = new \DateTime($cancellationPolicyData["penaltyDate"]['date']);
  1526.                         }catch(\Exception $e){
  1527.                         }
  1528.                     }
  1529.                     $penaltyDayObj = new \DateTime($cancellationPolicyData["penaltyDate"]->format('Y-m-d'));//need just the date part
  1530.                     $diff $quoteItem->getCheckInAsDate()->diff($penaltyDayObj);
  1531.                     $hour $cancellationPolicyData?$cancellationPolicyData["penaltyDate"]->format('H'):0;
  1532.                     if($quoteItem->getType() == QuoteItem::PRODUCT_TYPE_HOTEL && $diff->0){
  1533.                         $cancellationPolicyFrontEnd->setD($diff->days 1); //add one to account for the hours
  1534.                         $cancellationPolicyFrontEnd->setH($hour);
  1535.                     }else{
  1536.                         $cancellationPolicyFrontEnd->setD($diff->days);
  1537.                         $cancellationPolicyFrontEnd->setH($hour);
  1538.                     }
  1539.                     $cancellationPolicyFrontEnd->setTz($cancellationPolicyData["penaltyDate"]->getTimeZone());
  1540.                     $cancellationPolicyFrontEnd->setPenalty($cancellationPolicyData['penalty']);
  1541.                     $cancellationPolicyFrontEnd->setType($cancellationPolicyData['type']);
  1542.                 }
  1543.                 $supplierCancellationPolicyFrontEnds[] = $cancellationPolicyFrontEnd;
  1544.             }
  1545.         }
  1546.         foreach($oxCancellationPolicies as $oxCancellationPolicy){
  1547.             if($cancellationPolicyData $oxCancellationPolicy){
  1548.                 $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  1549.                 if(key_exists("penaltyDate"$cancellationPolicyData) && $cancellationPolicyData["penaltyDate"] && $quoteItem->getCheckIn()){
  1550.                     //Get days and time
  1551.                     if(is_string($cancellationPolicyData["penaltyDate"])){
  1552.                         try{
  1553.                             $penaltyDate date_create_from_format(\DATE_W3C$cancellationPolicyData["penaltyDate"]);
  1554.                             if (!$penaltyDate) {
  1555.                                 $penaltyDate date_create_from_format('Y-m-d H:i:s'$cancellationPolicyData["penaltyDate"]);
  1556.                                 //new \DateTime($cancellationPolicyData["penaltyDate"]);
  1557.                             }
  1558.                             $cancellationPolicyData["penaltyDate"] = $penaltyDate;
  1559.                         }catch(\Exception $e){
  1560.                         }
  1561.                     }
  1562.                     if(is_array($cancellationPolicyData["penaltyDate"])){
  1563.                         try{
  1564.                             $cancellationPolicyData["penaltyDate"] = new \DateTime($cancellationPolicyData["penaltyDate"]['date']);
  1565.                         }catch(\Exception $e){
  1566.                         }
  1567.                     }
  1568.                     $penaltyDayObj = new \DateTime($cancellationPolicyData["penaltyDate"]->format('Y-m-d'));//need just the date part
  1569.                     $diff $quoteItem->getCheckInAsDate()->diff($penaltyDayObj);
  1570.                     $hour $cancellationPolicyData?$cancellationPolicyData["penaltyDate"]->format('H'):0;
  1571.                     if($quoteItem->getType() == QuoteItem::PRODUCT_TYPE_HOTEL && $diff->0){
  1572.                         $cancellationPolicyFrontEnd->setD($diff->days 1); //add one to account for the hours
  1573.                         $cancellationPolicyFrontEnd->setH($hour);
  1574.                     }else{
  1575.                         $cancellationPolicyFrontEnd->setD($diff->days);
  1576.                         $cancellationPolicyFrontEnd->setH($hour);
  1577.                     }
  1578.                     $cancellationPolicyFrontEnd->setTz($cancellationPolicyData["penaltyDate"]->getTimeZone());
  1579.                     $cancellationPolicyFrontEnd->setPenalty($cancellationPolicyData['penalty']);
  1580.                     $cancellationPolicyFrontEnd->setType($cancellationPolicyData['type']);
  1581.                 }
  1582.                 $oxCancellationPolicyFrontEnds[] = $cancellationPolicyFrontEnd;
  1583.             }
  1584.         }
  1585.         //add new cancellation policy rows if any were added
  1586.         $requestQuoteItemData $request->request->get('my_quote_item');
  1587.         $countNewSupplierPolicies = isset($requestQuoteItemData) && isset($requestQuoteItemData['supplierCancellationPolicyFrontEnds']) ? count($requestQuoteItemData['supplierCancellationPolicyFrontEnds']):0;
  1588.         if(isset($requestQuoteItemData) && isset($requestQuoteItemData['supplierCancellationPolicyFrontEnds']) && count($supplierCancellationPolicyFrontEnds) < $countNewSupplierPolicies){
  1589.             //need to adjust the form
  1590.             $nextIndex count($supplierCancellationPolicyFrontEnds);
  1591.             foreach( $requestQuoteItemData['supplierCancellationPolicyFrontEnds'] as $index => $supplierCancellationPolicyFrontEndData){
  1592.                 if($index >= $nextIndex){
  1593.                     $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  1594.                     $cancellationPolicyFrontEnd->setD(intval($supplierCancellationPolicyFrontEndData['d']));
  1595.                     $cancellationPolicyFrontEnd->setH(intval($supplierCancellationPolicyFrontEndData['h']??0));
  1596.                     //$cancellationPolicyFrontEnd->setTz($cancellationPolicyData["penaltyDate"]->getTimeZone());
  1597.                     $cancellationPolicyFrontEnd->setPenalty(intval($supplierCancellationPolicyFrontEndData['penalty']));
  1598.                     $cancellationPolicyFrontEnd->setType($supplierCancellationPolicyFrontEndData['type']??"");
  1599.                     $supplierCancellationPolicyFrontEnds[] = $cancellationPolicyFrontEnd;
  1600.                 }
  1601.             }
  1602.         }
  1603.         $countNewOxPolicies = isset($requestQuoteItemData) && isset($requestQuoteItemData['oxCancellationPolicyFrontEnds']) ? count($requestQuoteItemData['oxCancellationPolicyFrontEnds']):0;
  1604.         if(isset($requestQuoteItemData) && isset($requestQuoteItemData['oxCancellationPolicyFrontEnds']) && count($oxCancellationPolicyFrontEnds) < $countNewOxPolicies){
  1605.             //need to adjust the form
  1606.             $nextIndex count($oxCancellationPolicyFrontEnds);
  1607.             foreach( $requestQuoteItemData['oxCancellationPolicyFrontEnds'] as $index => $oxCancellationPolicyFrontEndData){
  1608.                 if($index >= $nextIndex){
  1609.                     $cancellationPolicyFrontEnd = new CancellationPolicyModel();
  1610.                     $cancellationPolicyFrontEnd->setD(intval($oxCancellationPolicyFrontEndData['d']));
  1611.                     $cancellationPolicyFrontEnd->setH(intval($oxCancellationPolicyFrontEndData['h']??0));
  1612.                     //$cancellationPolicyFrontEnd->setTz($cancellationPolicyData["penaltyDate"]->getTimeZone());
  1613.                     $cancellationPolicyFrontEnd->setPenalty(intval($oxCancellationPolicyFrontEndData['penalty']));
  1614.                     $cancellationPolicyFrontEnd->setType($oxCancellationPolicyFrontEndData['type']??"");
  1615.                     $oxCancellationPolicyFrontEnds[] = $cancellationPolicyFrontEnd;
  1616.                 }
  1617.             }
  1618.         }
  1619.         //
  1620.         if(count($supplierCancellationPolicyFrontEnds) == 0){
  1621.             $supplierCancellationPolicyFrontEnds[] = new CancellationPolicyModel();
  1622.         }
  1623.         if(count($oxCancellationPolicyFrontEnds) == 0){
  1624.             $oxCancellationPolicyFrontEnds[] = new CancellationPolicyModel();
  1625.         }
  1626.     }
  1627.     private function convertStrToFloat($str)
  1628.     {
  1629.         return (float)str_replace(","""$str);
  1630.     }
  1631.     private function updateCustomRatesDetail(&$specificRateDetail$data$taxTableName$priceTableName$feeTableName$commissionFactor 1$hotelNetCommission false)
  1632.     {
  1633.         $ratesDetailTable $data['ratesDetail'];
  1634.         $somethingChange false;
  1635.         if (!$specificRateDetail && $ratesDetailTable) {
  1636.             foreach ($ratesDetailTable as $key => $rateDetail) {
  1637.                 $keyDate \DateTime::createFromFormat('m-d-Y'$key);
  1638.                 if ($keyDate === false) {
  1639.                     $keyDate \DateTime::createFromFormat('Y-m-d'$key);
  1640.                     if ($keyDate === false) {
  1641.                         $keyDate \DateTime::createFromFormat("Y-m-d\TH:i:s\Z"$key);
  1642.                     }
  1643.                 }
  1644.                 if ($keyDate !== false) {
  1645.                     // it's a date
  1646.                     $specificRateDetail[$keyDate->format("Y-m-d")] = array(
  1647.                         "fee" => $ratesDetailTable[$key][$feeTableName],
  1648.                         "date" => $keyDate->format("Y-m-d\TH:i:s\Z"),
  1649.                         "price" => $ratesDetailTable[$key][$priceTableName],
  1650.                         "taxPercentage" => $ratesDetailTable[$taxTableName]);
  1651.                     if ($hotelNetCommission && key_exists($hotelNetCommission$ratesDetailTable)) {
  1652.                         $specificRateDetail[$keyDate->format("Y-m-d")]["comPercentage"] = $ratesDetailTable[$hotelNetCommission];
  1653.                     }
  1654.                     $somethingChange true;
  1655.                 }
  1656.             }
  1657.         } else {
  1658.             foreach ($specificRateDetail as $key => $rateDetail) {
  1659.                 if (key_exists($key$ratesDetailTable)) {
  1660.                     $keyDate \DateTime::createFromFormat('d-m-Y'$key);
  1661.                     if ($keyDate === false) {
  1662.                         $keyDate \DateTime::createFromFormat('Y-m-d'$key);
  1663.                     }
  1664.                     $keyDate = new \DateTime($keyDate->format('Y-m-d')); //strip off the hours
  1665.                     $checkInDT = new \DateTime($data['my_quote_item']["quoteItem"]["checkIn"]);
  1666.                     $checkOutDT = new \DateTime($data['my_quote_item']["quoteItem"]["checkOut"]);
  1667.                     if (($keyDate >= $checkInDT) && ($keyDate <= $checkOutDT)) { //If it's visible
  1668.                         $rateDetailTableByDate $ratesDetailTable[$key];
  1669.                         if (($ratesDetailTable[$taxTableName]) != (string)$rateDetail['taxPercentage']) {
  1670.                             //Update taxPercentage
  1671.                             $specificRateDetail[$key]['taxPercentage'] = $ratesDetailTable[$taxTableName];
  1672.                             $somethingChange true;
  1673.                         }
  1674.                         if (($rateDetailTableByDate[$priceTableName] * $commissionFactor) != (string)$rateDetail['price']) {
  1675.                             //Update price
  1676.                             $specificRateDetail[$key]['price'] = $rateDetailTableByDate[$priceTableName] * $commissionFactor;
  1677.                             $somethingChange true;
  1678.                         }
  1679.                         if (($rateDetailTableByDate[$feeTableName]) != (string)$rateDetail['fee']) {
  1680.                             //Update fee
  1681.                             $specificRateDetail[$key]['fee'] = $rateDetailTableByDate[$feeTableName];
  1682.                             $somethingChange true;
  1683.                         }
  1684.                         if ($hotelNetCommission) {
  1685.                             $netRateDetailNetComKey key_exists('netRateDetailNetComTotal'$rateDetailTableByDate) ? 'netRateDetailNetComTotal' 'netRateDetailNetCom';
  1686.                             if (
  1687.                                 (!array_key_exists('comPercentage'$rateDetail) && array_key_exists($netRateDetailNetComKey$rateDetailTableByDate))
  1688.                                 ||
  1689.                                 (array_key_exists('comPercentage'$rateDetail) && array_key_exists($netRateDetailNetComKey$rateDetailTableByDate) && $rateDetailTableByDate[$netRateDetailNetComKey] != (string)$rateDetail['comPercentage'])
  1690.                             ) {
  1691.                                 $specificRateDetail[$key]["comPercentage"] = $rateDetailTableByDate[$netRateDetailNetComKey];
  1692.                                 $somethingChange true;
  1693.                             }
  1694.                         }
  1695.                     } else {
  1696.                         $specificRateDetail[$key] = array(
  1697.                             "fee" => 0,
  1698.                             "date" => $keyDate->format("Y-m-d\TH:i:s\Z"),
  1699.                             "price" => 0,
  1700.                             "taxPercentage" => 0);
  1701.                         if ($hotelNetCommission && key_exists($hotelNetCommission$ratesDetailTable)) {
  1702.                             $specificRateDetail[$key]["comPercentage"] = 0;
  1703.                         }
  1704.                         $somethingChange true;
  1705.                     }
  1706.                 }
  1707.             }
  1708.         }
  1709.         return $somethingChange;
  1710.     }
  1711.     /**
  1712.      * @param QuoteItem $quoteItem
  1713.      */
  1714.     private function getCancellationPolicyLabel(QuoteItem &$quoteItem)
  1715.     {
  1716.         //Get the array. Ex.:{"id": 24,"penaltyDate": "2021-04-27T00:00:00+00:00"}
  1717.         if ($cancellationPolicy $quoteItem->getCancellationPolicy()) {
  1718.             if(key_exists('type',$cancellationPolicy)){
  1719.                 $cancellationType $cancellationPolicy['type'];
  1720.                 if (($cancellationType == 'nights') && ($cancellationPolicy['penalty'] <= 1)) {
  1721.                     $cancellationType 'night';
  1722.                 }
  1723.             }
  1724.             $quoteItem->setCancellationPolicyLabel("");
  1725.             $quoteItem->setCancellationPolicy(array());
  1726.             if(key_exists('penalty',$cancellationPolicy)){
  1727.                 if ($cancellationDescription trim($cancellationPolicy['penalty'] . " " $cancellationType)) {
  1728.                     $cancellationPolicy['name'] = $cancellationPolicy['description'] = $cancellationDescription;
  1729.                     $cancellationPenaltyString "There is a penalty of " $cancellationDescription;
  1730.                     if ($cancellationPolicy['penaltyDate']) {
  1731.                         $cancellationPenaltyString .= " when cancelling after " $cancellationPolicy['penaltyDate']->format("M d, Y h:i A");
  1732.                     }
  1733.                     $quoteItem->setCancellationPenaltyDate($cancellationPolicy['penaltyDate']);
  1734.                     $quoteItem->setCancellationPolicyLabel($cancellationPenaltyString);
  1735.                     $penaltyDate $cancellationPolicy['penaltyDate'];
  1736.                     $cancellationPolicy['penaltyDate'] = (string)$penaltyDate->format("Y-m-d\TH:i:s\Z");
  1737.                 }
  1738.             } else {
  1739.                 $cancellationPolicy['penaltyDate'] = "";//null
  1740.                 $quoteItem->setCancellationPenaltyDate(null);
  1741.             }
  1742.             $quoteItem->setCancellationPolicy($cancellationPolicy);
  1743.         }
  1744.     }
  1745.     /**
  1746.      * @Route("/duplicate/{id}", name="my_quoteItem_duplicate", methods={"GET","POST"})
  1747.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  1748.      * @param QuoteItem|null $quoteItem
  1749.      * @return Response
  1750.      */
  1751.     public function duplicateQuoteItem(Request $requestCoreApi $coreApiQuoteItem $quoteItem null): Response
  1752.     {
  1753.         try {
  1754.             if (!$quoteItem) {
  1755.                 throw new \Exception('There is not a quote item to be duplicated.');
  1756.             }
  1757.             $newQuoteItem $quoteItem->getDuplicate();
  1758.             if ($newQuoteItem->isHotel() && !$newQuoteItem->isManuallyAdded()) {
  1759.                 //if the hotel is anything other than a manually added hotel, we will run a refresh price
  1760.                 //with the new dates, taking the latest prices from the API, if the price is not available
  1761.                 //anymore, we will set it as manual and set the princes to 0
  1762.                 if ($coreApi->refreshPrice($newQuoteItem)) {
  1763.                     //Change to manually
  1764.                     $newQuoteItem->setSource(QuoteItem::PRODUCT_SOURCE_MANUALLY);
  1765.                     $this->addFlash('warning''The rates were no longer available. This room has been set to manual rates');
  1766.                 }
  1767.             }
  1768.             $em $this->getDoctrine()->getManager();
  1769.             $em->persist($newQuoteItem);
  1770.             $em->flush();
  1771.             $em->refresh($quoteItem);
  1772.             //Check if it has any children (i.e. hotel services)
  1773.             if ($childrenQuoteItemList $quoteItem->getChildrenQuoteItems()) {
  1774.                 foreach ($childrenQuoteItemList as $childrenQuoteItem) {
  1775.                     $duplicateChildrenQuoteItem $childrenQuoteItem->getDuplicate();
  1776.                     $duplicateChildrenQuoteItem->setParentQuoteItem($newQuoteItem);
  1777.                     $em->persist($duplicateChildrenQuoteItem);
  1778.                     $em->flush();
  1779.                     $em->refresh($newQuoteItem);
  1780.                 }
  1781.             }
  1782.             $quoteItem->getQuote()->refreshQuoteDates();
  1783.             $em->persist($quoteItem->getQuote());
  1784.             $em->flush();
  1785.             $em->refresh($quoteItem);
  1786.             return $this->redirectToRoute('my_quoteItem_edit', array('id' => $newQuoteItem->getId()));
  1787.         } catch (\Exception $e) {
  1788.             $this->addFlash('error'"The Quote Item couldn't be duplicated");
  1789.         }
  1790.         return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  1791.     }
  1792.     private function getDataFormatString($date)
  1793.     {
  1794.         $keyDate \DateTime::createFromFormat('d-m-Y'$date);
  1795.         if ($keyDate === false) {
  1796.             return 'Y-m-d';
  1797.         } else {
  1798.             return 'd-m-Y';
  1799.         }
  1800.     }
  1801.     private function adjustRateDates(&$qiRateRows$checkInDate$checkOutDate$requestData$type): bool
  1802.     {
  1803.         $updated false;
  1804.         $newRateDetails $requestData['ratesDetail'];
  1805.         if ($checkInDate->format('Y-m-d') <= $checkOutDate->format('Y-m-d')) {
  1806.             $qiDatesArray array_keys($qiRateRows);
  1807.             $dateFormat self::getDataFormatString($qiDatesArray[0]);
  1808.             $validDatesArray = array();
  1809.             $testDate = clone $checkInDate;//new \DateTime($checkIn);
  1810.             while ($testDate->format('Y-m-d') <= $checkOutDate->format('Y-m-d')) {
  1811.                 $validDatesArray[] = $testDate->format($dateFormat);
  1812.                 $testDate->modify('+1 day');
  1813.             }
  1814.             $qiRateDetailTemp $qiRateRows;
  1815.             $model = array();//Remove extraneous ones
  1816.             foreach ($qiRateDetailTemp as $key => $data) {
  1817.                 $model $data;
  1818.                 $testDate \DateTime::createFromFormat($dateFormat$key);
  1819.                 if ($testDate === false) {
  1820.                     $tempFormat self::getDataFormatString($key);
  1821.                     $testDate \DateTime::createFromFormat($tempFormat$key);
  1822.                 }
  1823.                 if (!in_array($testDate->format($dateFormat), $validDatesArray)) {
  1824.                     unset($qiRateRows[$key]);
  1825.                     $updated true;
  1826.                 }
  1827.             }//add missing ones
  1828.             foreach ($model as $key => $val) {
  1829.                 $model[$key] = 0.0;
  1830.             }
  1831.             $qiDatesArray array_keys($qiRateRows);//Refresh
  1832.             foreach ($validDatesArray as $key) {
  1833.                 $dateLikeDataFormat \DateTime::createFromFormat($dateFormat$key);
  1834.                 if (!in_array($dateLikeDataFormat->format($dateFormat), $qiDatesArray)) {
  1835.                     $newDate $dateLikeDataFormat->format('d-m-Y');
  1836.                     if (!isset($newRateDetails[$newDate])) {
  1837.                         $newDate $dateLikeDataFormat->format('Y-m-d/Z00:00:00/T');
  1838.                     }
  1839.                     switch ($type) {
  1840.                         case 'net':
  1841.                             $model['fee'] = $newRateDetails[$newDate]['netRateDetailFee'] ?? 0;
  1842.                             $model['price'] = $newRateDetails[$newDate]['netRateDetailPrice'] ?? 0;
  1843.                             $model['taxPercentage'] = $newRateDetails['netTax'] ?? 0;
  1844.                             $model['comPercentage'] = $newRateDetails[$newDate]['netRateDetailNetCom'] ?? 0;
  1845.                             break;
  1846.                         case 'commission':
  1847.                         case 'retail'//Todo Retail price is actually a bit different
  1848.                             $model['fee'] = $newRateDetails[$newDate]['retailRateDetailFee'] ?? 0;
  1849.                             $model['price'] = $newRateDetails[$newDate]['retailRateDetailPrice'] ?? 0;
  1850.                             $model['taxPercentage'] = $newRateDetails['retailTax'] ?? 0;
  1851.                             break;
  1852.                     }
  1853.                     $newDate $dateLikeDataFormat->format($dateFormat);
  1854.                     $model['date'] = $newDate;
  1855.                     $qiRateRows[$newDate] = $model;
  1856.                     $updated true;
  1857.                 }
  1858.             }
  1859.         }
  1860.         return $updated;
  1861.     }
  1862.     /**
  1863.      * @Route("/removeFile/{id}/{filename}", name="my_quoteItem_remove_file", methods={"GET","POST"})
  1864.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  1865.      * @param QuoteItem|null $quoteItem
  1866.      * @param null $filename
  1867.      * @return Response
  1868.      */
  1869.     public function removeFile(QuoteItem $quoteItem null$filename null): Response
  1870.     {
  1871.         try {
  1872.             if (!$quoteItem) {
  1873.                 throw new \Exception('There is not a quote item.');
  1874.             }
  1875.             if (!$filename) {
  1876.                 throw new \Exception("Filename is missing.");
  1877.             }
  1878.             //Get the dir and filename together
  1879.             $filenameDir $this->getParameter('quote_item_file_directory') . "/" $filename;
  1880.             //Delete file from dir
  1881.             $filesystem = new Filesystem();
  1882.             $filesystem->remove($filenameDir);
  1883.             //Delete from json
  1884.             if ($quoteItem->removeFile($filename)) {
  1885.                 $em $this->getDoctrine()->getManager();
  1886.                 $em->persist($quoteItem);
  1887.                 $em->flush();
  1888.                 $this->addFlash('success''The file has been removed from the quote item');
  1889.             }
  1890.         } catch (\Exception $e) {
  1891.             if (isset($quoteItem)) {
  1892.                 $this->addFlash('error'"The file couldn't be removed from the quote item");
  1893.             } else {
  1894.                 $this->addFlash('error'$e->getMessage());
  1895.             }
  1896.         }
  1897.         if ($quoteItem) {
  1898.             return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  1899.         }
  1900.         return $this->redirectToRoute('all_quotes_index');
  1901.     }
  1902.     /**
  1903.      * @Route("/addPolicyRow/{id}/{type}", name="add_policy_row", methods={"GET"})
  1904.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  1905.      * @param Request $request
  1906.      * @param QuoteItem|null $quoteItem
  1907.      * @return Response
  1908.      */
  1909.     public function addPolicyRow(Request $requestQuoteItem $quoteItem null$type): Response
  1910.     {
  1911.         if (null == $quoteItem) {
  1912.             return $this->redirectToRoute('all_quotes_index');
  1913.         }
  1914.         if ($type == 'supplier') {
  1915.             $supplierCancellationPolicies $quoteItem->getCancellationPolicySupplier() ?? array();
  1916.             if (null != $supplierCancellationPolicies && array_key_exists('penaltyDate'$supplierCancellationPolicies)) { //make it an array of 1
  1917.                 $tempCancellationPolicies = array($supplierCancellationPolicies);
  1918.                 $supplierCancellationPolicies $tempCancellationPolicies;
  1919.             }
  1920.             if (count($supplierCancellationPolicies) > 0) {
  1921.                 //$newRow = array_fill_keys(array_keys($oxCancellationPolicies[0]),"");
  1922.                 $newRow end($supplierCancellationPolicies);
  1923.             } else {
  1924.                 $newRow = array("id" => """name" => """type" => """penalty" => """description" => """penaltyDate" => "");
  1925.             }
  1926.             $supplierCancellationPolicies[] = $newRow;
  1927.             if (count($supplierCancellationPolicies) == 1) {
  1928.                 $supplierCancellationPolicies[] = $newRow// add a second one
  1929.             }
  1930.             $quoteItem->setCancellationPolicySupplier($supplierCancellationPolicies);
  1931.         }
  1932.         $oxCancellationPolicies $quoteItem->getCancellationPolicyOx() ?? array();
  1933.         if (null != $oxCancellationPolicies && array_key_exists('penaltyDate'$oxCancellationPolicies)) { //make it an array of 1
  1934.             $tempCancellationPolicies = array($oxCancellationPolicies);
  1935.             $oxCancellationPolicies $tempCancellationPolicies;
  1936.         }
  1937.         if (count($oxCancellationPolicies) > 0) {
  1938.             //$newRow = array_fill_keys(array_keys($oxCancellationPolicies[0]),"");
  1939.             $newRow end($oxCancellationPolicies);
  1940.         } else {
  1941.             $newRow = array("id" => """name" => """type" => """penalty" => """description" => """penaltyDate" => "");
  1942.         }
  1943.         $oxCancellationPolicies[] = $newRow;
  1944.         if (count($oxCancellationPolicies) == 1) {
  1945.             $oxCancellationPolicies[] = $newRow// add a second one
  1946.         }
  1947.         $quoteItem->setCancellationPolicyOx($oxCancellationPolicies);
  1948.         $em $this->getDoctrine()->getManager();
  1949.         $em->persist($quoteItem);
  1950.         $em->flush();
  1951.         return $this->redirectToRoute('my_quoteItem_edit', array('id' => $quoteItem->getId()));
  1952.     }
  1953.     /**
  1954.      * @Route("/setQcAgent/{id}/{qcAgent}", name="set_qc_agent", methods={"GET","POST"})
  1955.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  1956.      * @param QuoteItem|null $quoteItem
  1957.      * @param User|null $qcAgent
  1958.      * @return Response
  1959.      */
  1960.     public function SetQcAgent(EntityManagerInterface $emQuoteItem $quoteItem nullUser $qcAgent null): Response
  1961.     {
  1962.         if (isset($quoteItem)) {
  1963.             $quoteItem->setAssignedQcAgent($qcAgent);
  1964.             $em->persist($quoteItem);
  1965.             $em->flush();
  1966.             return new JsonResponse(array('success' => true));
  1967.         } else {
  1968.             return new JsonResponse(array('success' => false));
  1969.         }
  1970.     }
  1971.     public function setOriginalCurrencyObj(&$request, &$quoteItem)
  1972.     {
  1973.         if ($request->request->get('displayInOriginalCurrency') != null) {
  1974.             $quoteItem->setDisplayInOriginalCurrency($request->request->get('displayInOriginalCurrency') ?? false);
  1975.         } elseif ($quoteItem->getDisplayInOriginalCurrency() == null) {
  1976.             $quoteItem->setDisplayInOriginalCurrency(false);
  1977.         }
  1978.         $currencyShortName $request->request->get('my_quote_item')['quoteItem']['originalCurrency'] ?? null;
  1979.         if ($currencyShortName != null) {
  1980.             $currencyObj $this->getDoctrine()->getRepository(Currency::class)->findOneBy(['shortName' => $currencyShortName]);
  1981.             $quoteItem->setOriginalCurrency($currencyObj);
  1982.             $requestQuoteItem $request->request->get('my_quote_item');
  1983.             $requestQuoteItem['quoteItem']['originalCurrency'] = $currencyObj;
  1984.             $request->request->set('my_quote_item'$requestQuoteItem);
  1985.         }
  1986.     }
  1987.     private function ClearBadFiles(FormInterface &$form)
  1988.     {
  1989.         //If the form has an error on the attachFile, then removed to not show on the modal form.
  1990.         if ($form->isSubmitted() && !$form->isValid()) {
  1991.             /**
  1992.              * @var FormErrorIterator $formErrors
  1993.              * @var ConstraintViolation $cause
  1994.              */
  1995.             $cause $form->getErrors(true)->getChildren()->getCause();
  1996.             if ($cause && method_exists($cause"getPropertyPath")) {
  1997.                 if ($cause->getPropertyPath() == "children[attachFile].data") {
  1998.                     $form->get('attachFile')->clearErrors();
  1999.                 }
  2000.             } elseif ($form->get('attachFile')->getErrors()) {
  2001.                 $form->get('attachFile')->clearErrors();
  2002.             }
  2003.         }
  2004.         //END If the form has an error on the attachFile, then removed to not show on the modal form.
  2005.     }
  2006.     /**
  2007.      * @Route("/changeQuote", name="quoteitem_change_quote", methods={"POST"})
  2008.      */
  2009.     public function changeQuoteAction(Request $requestQuoteItemRepository $quoteItemRepository): Response
  2010.     {
  2011.         try {
  2012.             $formSubmitted false;
  2013.             $em $this->getDoctrine()->getManager();
  2014.             if ($changeQuote $request->get('changeQuote')) {
  2015.                 //Form sent
  2016.                 if (!$quoteItemId $changeQuote['quoteItem']) {
  2017.                     throw new \Exception("Quote Item was not found");
  2018.                 }
  2019.                 if (!$quoteId $changeQuote['quote']) {
  2020.                     throw new \Exception("Quote was not selected");
  2021.                 }
  2022.                 if (!$quote $em->getRepository(Quote::class)->find($quoteId)) {
  2023.                     throw new \Exception("Quote selected was not found");
  2024.                 }
  2025.                 $formSubmitted true;
  2026.             } else {
  2027.                 //modal called first time
  2028.                 if (!$quoteItemId $request->get('quoteItemId')) {
  2029.                     throw new \Exception("Quote Item was not found");
  2030.                 }
  2031.             }
  2032.             /**
  2033.              * @var QuoteItem $quoteItem
  2034.              */
  2035.             if (!$quoteItem $em->getRepository(QuoteItem::class)->find($quoteItemId)) {
  2036.                 throw new \Exception("Quote Item was not found");
  2037.             }
  2038.             if (!$quoteItem->canQuoteBeChanged()) {
  2039.                 throw new \Exception("The quote cannot be changed for this quote item");
  2040.             }
  2041.             if ($formSubmitted) {
  2042.                 $quoteItem->setQuote($quote);
  2043.                 foreach ($quoteItem->getChildrenQuoteItems() as $childQuoteItem) {
  2044.                     $childQuoteItem->setQuote($quote);
  2045.                     $em->persist($childQuoteItem);
  2046.                 }
  2047.                 $em->persist($quoteItem);
  2048.                 $em->flush();
  2049.                 $this->addFlash('success''The Quote Item has been successfully moved to the quote selected');
  2050.                 return $this->redirectToRoute('all_quotes_index');
  2051.             }
  2052.             $quoteList $em->getRepository(Quote::class)->findAllQuotesExcept($quoteItem->getQuote()->getId());
  2053.             return $this->render('backOffice/quoteItem/_modalChangeQuoteContent.html.twig', [
  2054.                 'quoteItem' => $quoteItem,
  2055.                 'quoteList' => $quoteList
  2056.             ]);
  2057.         } catch (\Exception $e) {
  2058.             $this->addFlash('error'"The Quote Item couldn't be moved to the quote selected. Error: " $e->getMessage());
  2059.             return $this->redirectToRoute('all_quotes_index');
  2060.         }
  2061.     }
  2062.     /**
  2063.      * @Route("/paymentStatus/{id}", name="payment_status", methods={"GET","POST"})
  2064.      * @Security("is_granted('ROLE_USER_EDIT_CUSTOMER_ACCOUNT')")
  2065.      * @return Response
  2066.      */
  2067.     public function getPaymentStatus(Request $requestQuoteItem $quoteItemQuickbooksAPI $quickbooksAPI): Response
  2068.     {
  2069.         $payments null;
  2070.         try {
  2071.             $payments $quickbooksAPI->getPayment($quoteItem->getQuickbookPayableReferenceId());
  2072.             $brian $payments;
  2073.         } catch (\Exception $e) {
  2074.             $message $e->getMessage();
  2075.             return JsonResponse::fromJsonString($message);
  2076.         }
  2077.         return JsonResponse::fromJsonString('{"status": "ok"}');
  2078.     }
  2079. }