src/Service/TwigGlobalVariables.php line 99

Open in your IDE?
  1. <?php
  2. //src/Service/TwigGlobalVariables.php
  3. namespace App\Service;
  4. use App\Entity\Cart;
  5. use App\Entity\City;
  6. use App\Entity\DeliveryRoute;
  7. use Symfony\Component\DependencyInjection\ContainerInterface;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use App\Service\UserInterface;
  10. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  11. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  12. use App\Entity\Product;
  13. use App\Entity\Category;
  14. use App\Entity\Company;
  15. use App\Entity\CartProduct;
  16. use App\Entity\OmeloPage;
  17. use App\Entity\ProductSponsored;
  18. use App\Entity\CompanyAssociation;
  19. use App\Entity\Variable;
  20. use App\Entity\PickupLocations;
  21. use App\Service\UserService;
  22. use App\Service\MessageService;
  23. use App\Service\DistributorService;
  24. use App\Service\VariableService;
  25. use App\Repository\NotificationRepository;
  26. use DateTime;
  27. use Symfony\Component\Routing\Route;
  28. use function GuzzleHttp\Psr7\str;
  29. class TwigGlobalVariables
  30. {
  31.     private $userServ;
  32.     private $messageServ;
  33.     private $containerInter;
  34.     private $notificationRepo;
  35.     private $distribServ;
  36.     private $variableServ;
  37.     private $trackPodServ;
  38.     public function __construct(SessionInterface $sessionEntityManagerInterface $emContainerInterface $containerNotificationRepository $notifMessageService $messageServUserService $userServDistributorService $distVariableService $variableServ,TrackPodAPIService $trackPodAPIService){
  39.         $this->session $session;
  40.         $this->em $em;
  41.         $this->containerInter $container;
  42.         $this->notificationRepo $notif;
  43.         $this->messageServ $messageServ;
  44.         $this->userServ $userServ;
  45.         $this->distribServ $dist;
  46.         $this->variableServ $variableServ;
  47.         $this->trackPodServ$trackPodAPIService;
  48.     }
  49.     /*
  50.      * Return the StarterKits for promo a bit everywhere
  51.      */
  52.     public function getStarterKits(){
  53.         return $this->em->getRepository(ProductSponsored::class)->findInModal();
  54.     }
  55.     /*
  56.      * Return a boolean if we display the starter kits or no
  57.      */
  58.     public function getDisplayStarterKits()
  59.     {
  60.         if ($this->session->get('DO_NOT_DISPLAY_STARTERKITS') == "TRUE") {
  61.           return false;
  62.         }
  63.         if($this->getStarterKits()){
  64.             //Not a loggued user we display
  65.             if(!$this->userServ->getUser()){
  66.                 return true;
  67.             }
  68.             //If we don'T have the last 4 digits mean the user never bought anything
  69.             if(empty($this->userServ->getUser()->getPaymentLast4digits()))
  70.                 return true;
  71.         }
  72.         return false;
  73.     }
  74.     public function getUser(){
  75.         return $this->userServ->getUser();
  76.     }
  77.     /*
  78.      * Notifications
  79.      */
  80.     public function getNewNotifications(){
  81.         $newNotif $this->notificationRepo->findNewNotifications();
  82.         return $newNotif;
  83.     }
  84.     /*
  85.      * Get Cart
  86.      */
  87.     public function getCart(){
  88.         return $this->userServ->getCart();
  89.     }
  90.     /*
  91.      * Get Favorite
  92.      */
  93.     public function getFavorites(){
  94.         return $this->userServ->getFavorites();
  95.     }
  96.     /*
  97.      * Check if product it favorite
  98.      */
  99.     public function hasFavorite($product){
  100.         foreach($this->userServ->getFavorites() as $f){
  101.             if($f->getProduct() == $product)
  102.                 return true;
  103.         }
  104.         return false;
  105.     }
  106.     /*
  107.      * New Message
  108.      */
  109.     public function getNewMessages(){
  110.             $newMsg $this->messageServ->getNewMessagesIn('inbox');
  111.             return $newMsg;
  112.     }
  113.     /*
  114.      * The frontend Menu
  115.      */
  116.     public function menu(){
  117.         $menu $this->em
  118.             ->getRepository(Category::class)
  119.             ->getTreeMenu();
  120.             // ->findBy(array(
  121.             //     'subCategory' => null
  122.             //     ),
  123.             //     array('placement' => 'ASC'))
  124.             //     ;
  125.         return $menu;
  126.     }
  127.     /*
  128.      * The frontend Menu
  129.      */
  130.     public function getHasProducts($category){
  131.         $hasProducts $this->em
  132.             ->getRepository(Product::class)
  133.             ->countProductsInCategory($category);
  134.         return $hasProducts;
  135.     }
  136.     /*
  137.      * Return the footer
  138.      */
  139.     public function footer(){
  140.         $data = array();
  141.         $footer $this->em
  142.             ->getRepository(OmeloPage::class)
  143.             ->findBy(array(
  144.                 'template' => 'footer.html.twig'
  145.                 )
  146.             );
  147.         if($footer){
  148.             $footer current($footer);
  149.             return json_decode($footer->getContent());
  150.         }else
  151.             return false;
  152.     }
  153.     /*
  154.      * Return the company Terms
  155.      */
  156.     public function getCompanyTerms(){
  157.         $data = array();
  158.         $terms $this->em
  159.             ->getRepository(OmeloPage::class)
  160.             ->findBy(array(
  161.                 'url' => 'reglement-vendeurs'
  162.                 )
  163.             );
  164.         if($terms){
  165.             $terms current($terms);
  166.             return $terms->getMainContent();
  167.         }else
  168.             return false;
  169.     }
  170.     public function getTimeStamp(){
  171.         return mktime();
  172.     }
  173.     public function cssVersion(){
  174.         $date = new \DateTime();
  175.         return $date->format('YmdH');
  176.     }
  177.     public function getEstimationShipping(Product $product){
  178.         return $this->getEstimationShippingRoute($product)['date'];
  179.     }
  180.     public function getLastUsedShippingAddress() {
  181.       $shippingAddress false;
  182.       $currentCart $this->getCart();
  183.       if ($currentCart) {
  184.         $shippingAddress $currentCart->getShippingAddress();
  185.       }
  186.       if (!$shippingAddress) {
  187.         // use last cart address if available
  188.         if (($lastCart $this->em->getRepository(Cart::class)->lastUserPaidCart($this->getUser())) !== null){
  189.           $shippingAddress $lastCart->getShippingAddress();
  190.         }
  191.       }
  192.       # else use user's last created address
  193.       if ($shippingAddress === null){
  194.           $addresses $this->getUser()->getShippingAddresses();
  195.           if (count($addresses) > 0){
  196.               $shippingAddress $addresses[count($addresses)-1];
  197.           }
  198.       }
  199.       return $shippingAddress;
  200.     }
  201.     public function getEstimationShippingRoute(Product $product){
  202.         $isFreshProduct $product->getIsRefrigerated() || $product->getIsFroozen();
  203.         // define minimal departure date (time > 12P PM => after tomorrow, else tomorrow    )
  204.         $productDepartureDate = new \DateTime();
  205.         $productDepartureDate $productDepartureDate->modify('+1 day');
  206.         if ($productDepartureDate->format('H') >= 12){
  207.             $productDepartureDate $productDepartureDate->modify('+1 day');
  208.         }
  209.         $productDepartureDate $productDepartureDate->setTime(0,0,0);
  210.         // JIT and special offers can only be sent on next tuesday
  211.         if($product->getIsJustinTime()) {
  212.             $todaysDate = new \DateTime();
  213.             $productDepartureDate = !empty($product->getJustInTimeDeliveryDate()) ?
  214.                 $product->getJustInTimeDeliveryDate() : $todaysDate->modify("next tuesday");
  215.             /*
  216.               if today is monday, add one week to the departure date
  217.               it will become next tuesday of next week
  218.             */
  219.             if (
  220.               date("w") == // 0=sunday,1=monday
  221.             ) {
  222.               $dt = new \DateTime();
  223.               $dt->setTimestamp(strtotime("+1 week"$productDepartureDate->format("U")));
  224.               $productDepartureDate $dt;
  225.             }
  226.             $productDepartureDate $productDepartureDate->setTime(0,0,0);
  227.         }
  228.         else if($product->getCompany()->getId() == 181)
  229.             $productDepartureDate =  new \DateTime("next tuesday");
  230.         // use cart shipping addresse if setted
  231.         $shippingAddress $this->userServ->getCart()->getShippingAddress();
  232.         if ($shippingAddress == null && $this->getUser() !== null){
  233.           $lastShippingAddress $this->getLastUsedShippingAddress();
  234.           if ($lastShippingAddress) {
  235.             $shippingAddress $lastShippingAddress;
  236.           }
  237.         }
  238.         # estimation for city from cart address
  239.         $bestEstimation null;
  240.         if ( $shippingAddress !== null){
  241.             $cityName $shippingAddress->getCity();
  242.             $city $this->em->getRepository(City::class)->findOneBy(['name' => $cityName]);
  243.             $routes $city != null $city->getDeliveryRoutes() : $this->em->getRepository(DeliveryRoute::class)
  244.                 ->findBy(['type' => 'maturin']);
  245.             # get shipping address city
  246.             # get city's available delivery routes
  247.             $estimations = [];
  248.             foreach ($routes as $route){
  249.                 // process only maturin routes
  250.                 if ($route->getType() !== DeliveryRoute::MATURIN_TYPE)
  251.                     continue;
  252.                 if ($isFreshProduct && $route->getName() === 'Pas de frais')
  253.                     break;
  254.                 /*
  255.                  * exclude route if not matching product requirements
  256.                  */
  257.                 if ($product->getIsRefrigerated() && !$route->isRefrigeratedAllowed())
  258.                     continue;
  259.                 if ($product->getIsFroozen() && !$route->isFrozenAllowed())
  260.                     continue;
  261.                 if (!$product->getIsRefrigerated() && !$product->getIsFroozen() && !$route->isDryAllowed())
  262.                     continue;
  263.                 // add estimation to list
  264.                 $estimations []= [
  265.                     'date' => $route->getDeliveryDateEstimation(clone $productDepartureDate),
  266.                     'route' => $route
  267.                 ];
  268.             }
  269.             # find best estimation from list
  270.             foreach ($estimations as $estimation){
  271.                 if ($bestEstimation === null || $estimation['date'] < $bestEstimation['date']){
  272.                     $bestEstimation $estimation;
  273.                 }
  274.             }
  275.         }
  276.         # compare best estimation against purolator and keep the best one
  277.         $puroEstimation null;
  278.         if (($puro $this->em->getRepository(DeliveryRoute::class)->findOneBy([
  279.                 'type' => $isFreshProduct DeliveryRoute::PURO_FRAIS_TYPE DeliveryRoute::PURO_SEC_TYPE
  280.             ])) !== null)
  281.         {
  282.             $puroEstimation = [
  283.                 'date' => $puro->getDeliveryDateEstimation(clone $productDepartureDate),
  284.                 'route' => $puro
  285.             ];
  286.             if ($bestEstimation === null)
  287.                 return $puroEstimation;
  288.             if (is_bool($puroEstimation['date']) && $bestEstimation) {
  289.               return $bestEstimation;
  290.             }
  291.             if (is_bool($bestEstimation['date']) && $puroEstimation) {
  292.               return $puroEstimation;
  293.             }
  294.             return ($puroEstimation['date']->format('W') < $bestEstimation['date']->format('W')) ? $puroEstimation $bestEstimation;
  295.         }
  296.         return [
  297.             'date' => $this->distribServ->getEstimationShippingForProduct($product),
  298.             'route' => null
  299.         ];
  300.     }
  301.     public function getEstimationShippingForMaturinProducts($cart){
  302.         $late = new \DateTime();
  303.         foreach($cart->getProducts() as $p){
  304.             $est $this->getEstimationShipping($p->getProduct());
  305.             if($est $late)
  306.                 $late $est;
  307.         }
  308.         return $late;
  309.     }
  310.     public function getEstimationShippingRouteForMaturinProducts($cart$city null){
  311.         $late = ['date' => new \DateTime(), 'route' => null];
  312.         $datePayment = new \DateTime();
  313.         if ($cart->getDatePayment()) {
  314.           $datePayment = clone $cart->getDatePayment();
  315.         }
  316.         foreach($cart->getProducts() as $p){
  317.             $est $this->getMaintenanceEstimationShippingRoute($p->getProduct(), $datePayment$city);
  318.             if($est['date'] > $late['date'])
  319.                 $late $est;
  320.         }
  321.         return $late;
  322.     }
  323.     public function getShippingEstimateDate($cart){
  324.         return $this->getMaintenanceEstimationShippingForMaturinProducts($cart);
  325.     }
  326.     public function isAllowedToModify(Product $product){
  327.         //We use the admin bundle for now, for our own staff only
  328.         return $this->userServ->isAllowedToMakeBundles();
  329.     }
  330.     public function getGlobalPickUpLocations() {
  331.         $returnedLocations = [];
  332.         $pickupLocations $this->em->getRepository(PickupLocations::class)->findBy(array('locationStatus' => 'ACTIVE'));
  333.         foreach($pickupLocations as $location) {
  334.             $getRoutes $this->em->getRepository(City::class)->findBy(['name' => trim($location->getLocationCity())]);
  335.         
  336.             $returnedLocations[] = [
  337.             "value" => $location->getId(),
  338.             "text" => $location->getLocationName()." - ".$location->getLocationAddress(),
  339.             ];
  340.         }
  341.         return $returnedLocations;
  342.     }
  343.     public function getGlobalPickUpLocation() {
  344.       
  345.       $returnedLocation false;
  346.       $pickupLocations $this->em->getRepository(PickupLocations::class)->findBy(array('locationStatus' => 'ACTIVE'));
  347.       if ($pickupLocations) {
  348.         $pickupLocation current($pickupLocations);
  349.         $pickupLocationAddress $pickupLocation->getLocationAddress();
  350.         $pickupLocationName $pickupLocation->getLocationName();
  351.         if ($pickupLocationAddress) {
  352.           $returnedLocation $pickupLocationName." - ".$pickupLocationAddress;
  353.         }
  354.       }
  355.       return $returnedLocation;
  356.     }
  357.     public function getGlobalPickUpSchedule() {
  358.       $returnedSchedule false;
  359.       $pickupLocations $this->em->getRepository(PickupLocations::class)->findBy(array('locationStatus' => 'ACTIVE'));
  360.       if ($pickupLocations) {
  361.         $pickupLocation current($pickupLocations);
  362.         $pickupLocationSchedule $pickupLocation->getLocationSchedule();
  363.         if ($pickupLocationSchedule) {
  364.           $pickupLocationSchedule json_decode($pickupLocationScheduletrue);
  365.           $returnedSchedule json_encode($pickupLocationSchedule["pickUpSchedule"]);
  366.         }
  367.       }
  368.       return $returnedSchedule;
  369.     }
  370.     public function getGlobalPickUpSchedules() {
  371.       $returnedSchedules = [];
  372.       $pickupLocations $this->em->getRepository(PickupLocations::class)->findBy(array('locationStatus' => 'ACTIVE'));
  373.       foreach($pickupLocations as $pickupLocation) {
  374.         $pickupLocationSchedule $pickupLocation->getLocationSchedule();
  375.         if ($pickupLocationSchedule) {
  376.           $pickupLocationSchedule json_decode($pickupLocationScheduletrue);
  377.           $returnedSchedules[$pickupLocation->getId()] = $pickupLocationSchedule["pickUpSchedule"];
  378.         }
  379.       }
  380.       return $returnedSchedules;
  381.     }
  382.     public function hasGlobalPickUpEnabled() {
  383.       $pickupLocations $this->em->getRepository(PickupLocations::class)->findBy(array('locationStatus' => 'ACTIVE'));
  384.       if (!empty($pickupLocations)) {
  385.         return true;
  386.       }
  387.       return false;
  388.     }
  389.     /*
  390.     * For the association tell if the user is staying inside a association
  391.     */
  392.     public function getAssociationUserIsBrowsing(){
  393.         return $this->userServ->getAssociationUserIsBrowsing();
  394.     }
  395.     public function getVariableValueByCodeName($codeNameCompany $company=null){
  396.             return $this->variableServ->getValueByCodeName($codeName$company);
  397.     }
  398.     public function getPickupChoiceForCurrentAssociation(): array {
  399.         $association $this->getAssociationUserIsBrowsing();
  400.         $available = [];
  401.         if ($association){
  402.             $pickupScheduleVar $association->getVariableByCodeName('orders.pickUpSchedule');
  403.             if ($pickupScheduleVar && $pickupScheduleVar->getValueType() == 3) {
  404.                 $choices $pickupScheduleVar->getJsonValueAsArray();
  405.                 $delay $association->getVariableByCodeName('orders.prepareDelay');
  406.                 if ($delay)
  407.                     $delay = (int)$delay->getValue();
  408.                 else
  409.                     $delay 2// default 2
  410.                 $currentDayOfWeek date("N");
  411.                 $dayMap = ['Monday''Tuesday''Wednesday''Thursday''Friday''Saturday','Sunday'];
  412.                 $notBefore = new \DateTime('today');
  413.                 $notBefore->modify("+ $delay day");
  414.                 foreach ($choices as $dayInt => $periods) {
  415.                     $next = new \DateTime('next ' $dayMap[((int)$dayInt) - 1]);
  416.                     if ($next $notBefore) {
  417.                         $next->modify('+ 1 week');
  418.                     }
  419.                     foreach ($periods as $period) {
  420.                         $available [] = [
  421.                             'day' => $next,
  422.                             'start' => $period[0],
  423.                             'end' => $period[1],
  424.                         ];
  425.                     }
  426.                 }
  427.             }
  428.         }
  429.         return $available;
  430.     }
  431.     public function getIsDev(){
  432.         return $_ENV['APP_ENV'] !== 'prod';
  433.     }
  434.     public function getStripeAPIPKey(){
  435.         return $_ENV['STRIPE_API_PKEY'];
  436.     }
  437.     /**
  438.      * Check if order pack up is possible for cart product
  439.      * It looks into product association options
  440.      *
  441.      * @param Cart $cart
  442.      * @return bool
  443.      */
  444.     public function canPackup(Cart $cart):int{
  445.         foreach ($cart->getProducts() as $cartProduct){
  446.             if ($cartProduct->getAddedWhenBeingInAssociation()){
  447.                 return $cartProduct->getAddedWhenBeingInAssociation()->canPackUp();
  448.             }
  449.         }
  450.         return 0;
  451.     }
  452.     public function isAllowedToMakeBundles(){
  453.         return $this->userServ->isAllowedToMakeBundles();
  454.     }
  455.     public function getDeliveryBreadCrumpText(){
  456.         $textParts = [];
  457.         // check for delivery
  458.         if ($this->getCart()->hasMaturinShipping() || $this->getCart()->getHasCustomShipping()){
  459.             $textParts []= 'Livraison';
  460.         }
  461.         // check for pickup
  462.         if ($this->getCart()->hasPickup()){
  463.             $textParts []= 'Cueillette';
  464.         }
  465.         return count($textParts) > implode(' / '$textParts) : 'Livraison';
  466.     }
  467.     public function getAssociationNames($cart){
  468.         $associationNames = [];
  469.         foreach ($cart->getProducts() as $cartProduct) {
  470.             if (($association $cartProduct->getAddedWhenBeingInAssociation()) != null)
  471.             {
  472.                 $name $association->getName();
  473.                 $name str_replace('le '''$name);
  474.                 $name str_replace('Le '''$name);
  475.                 $name str_replace('la '''$name);
  476.                 $name str_replace('La '''$name);
  477.                 if (!in_array($name$associationNames))
  478.                     $associationNames[]=$name;
  479.             }
  480.         }
  481.         return implode(', '$associationNames);
  482.     }
  483.     /**
  484.      * Check if user is admin of association that contains company
  485.      *
  486.      * @param Company $company
  487.      * @return bool
  488.      */
  489.     public function userIsAssociationAdmin(Company $company): bool{
  490.         $user $this->getUser();
  491.         if ($user){
  492.             $association $user->getMakeCompanyForAssociation();
  493.             if ($association){
  494.                 return $association->getCompanies()->contains($company);
  495.             }
  496.         }
  497.         return false;
  498.     }
  499.     /**
  500.      * Check if user as Maturin Admin Role or is Super User
  501.      * @return bool
  502.      */
  503.     public function userIsMaturinAdmin(): bool{
  504.         $user $this->getUser();
  505.         return $user && (
  506.             $user->isGranted('ROLE_SUPER_ADMIN')
  507.                 || $user->isGranted('ROLE_ADMIN_MATURIN')
  508.             );
  509.     }
  510.     public function add48hToDate(\DateTime $startDate): \DateTime{
  511.         $endDate = clone $startDate;
  512.         $endDate  $endDate->modify('+ 2 days');
  513.         if ($endDate->format('N') >= 6)
  514.             $endDate  $endDate->modify('+ 2 days');
  515.         return $endDate ;
  516.     }
  517.     public function getMaintenanceEstimationShippingRoute(Product $product,\DateTime $date$city null){
  518.         $todaysDate = clone $date;
  519.         $isFreshProduct $product->getIsRefrigerated() || $product->getIsFroozen();
  520.         // define minimal departure date (time > 12P PM => after tomorrow, else tomorrow    )
  521.         $productDepartureDate = clone $todaysDate;
  522.         $productDepartureDate $productDepartureDate->modify('+1 day');
  523.         if ($productDepartureDate->format('H') >= 12) {
  524.             $productDepartureDate $productDepartureDate->modify('+1 day');
  525.         }
  526.         $productDepartureDate $productDepartureDate->setTime(0,0,0);
  527.         // JIT and special offers can only be sent on next tuesday
  528.         if($product->getIsJustinTime()) {
  529.             if (!empty($product->getJustInTimeDeliveryDate())) {
  530.               $productDepartureDate $product->getJustInTimeDeliveryDate();
  531.             } else {
  532.               $productDepartureDate = clone $todaysDate;
  533.               $productDepartureDate->modify("next tuesday");
  534.             }
  535.             /*
  536.               if today is monday, add one week to the departure date
  537.               it will become next tuesday of next week
  538.             */
  539.             if (
  540.               date("w"$todaysDate->getTimestamp()) == // 0=sunday,1=monday
  541.             ) {
  542.               $productDepartureDate->modify("+1 week");
  543.             }
  544.         } else {
  545.           if ($product->getCompany()->getId() == 181) {
  546.             $productDepartureDate $todaysDate->modify("next tuesday");
  547.           }
  548.         }
  549.         // use cart shipping addresse if setted
  550.         $shippingAddress $this->userServ->getCart()->getShippingAddress();
  551.         if ($shippingAddress == null && $this->getUser() !== null){
  552.             // use last cart address if available
  553.             if (($lastCart $this->em->getRepository(Cart::class)->lastUserPaidCart($this->getUser())) !== null){
  554.                 $shippingAddress $lastCart->getShippingAddress();
  555.             }
  556.             # else use user's last created address
  557.             if ($shippingAddress === null){
  558.                 $addresses $this->getUser()->getShippingAddresses();
  559.                 if (count($addresses) > 0){
  560.                     $shippingAddress $addresses[count($addresses)-1];
  561.                 }
  562.             }
  563.         }
  564.         $cityName=null;
  565.         if ($city != null){
  566.             $cityName $city;  
  567.         }
  568.         if ($city == null && $shippingAddress !== null){
  569.             $cityName $shippingAddress->getCity();  
  570.         }
  571.         # estimation for city from cart address
  572.         $bestEstimation null;
  573.         if ( $shippingAddress !== null){
  574.             
  575.             $city $this->em->getRepository(City::class)->findOneBy(['name' => $cityName]);
  576.             $routes $city != null $city->getDeliveryRoutes() : $this->em->getRepository(DeliveryRoute::class)
  577.                 ->findBy(['type' => 'maturin']);
  578.             # get shipping address city
  579.             # get city's available delivery routes
  580.             $estimations = [];
  581.             foreach ($routes as $route){
  582.                 // process only maturin routes
  583.                 if ($route->getType() !== DeliveryRoute::MATURIN_TYPE)
  584.                     continue;
  585.                 if ($isFreshProduct && $route->getName() === 'Pas de frais')
  586.                     break;
  587.                 /*
  588.                  * exclude route if not matching product requirements
  589.                  */
  590.                 if ($product->getIsRefrigerated() && !$route->isRefrigeratedAllowed())
  591.                     continue;
  592.                 if ($product->getIsFroozen() && !$route->isFrozenAllowed())
  593.                     continue;
  594.                 if (!$product->getIsRefrigerated() && !$product->getIsFroozen() && !$route->isDryAllowed())
  595.                     continue;
  596.                 // add estimation to list
  597.                 $estimations = [
  598.                     'date' => $route->getDeliveryDateEstimation(clone $productDepartureDate),
  599.                     'route' => $route
  600.                 ];
  601.                 return $estimations;
  602.             }
  603.             # find best estimation from list
  604.             foreach ($estimations as $estimation){
  605.                 if ($bestEstimation === null || $estimation['date'] < $bestEstimation['date']){
  606.                     $bestEstimation $estimation;
  607.                 }
  608.             }
  609.         }
  610.         # compare best estimation against purolator and keep the best one
  611.         $puroEstimation null;
  612.         if (($puro $this->em->getRepository(DeliveryRoute::class)->findOneBy([
  613.                 'type' => $isFreshProduct DeliveryRoute::PURO_FRAIS_TYPE DeliveryRoute::PURO_SEC_TYPE
  614.             ])) !== null)
  615.         {
  616.             $puroEstimation = [
  617.                 'date' => $puro->getDeliveryDateEstimation(clone $productDepartureDate),
  618.                 'route' => $puro
  619.             ];
  620.             if ($bestEstimation === null)
  621.                 return $puroEstimation;
  622.             if (is_bool($puroEstimation['date']) && $bestEstimation) {
  623.               return $bestEstimation;
  624.             }
  625.             if (is_bool($bestEstimation['date']) && $puroEstimation) {
  626.               return $puroEstimation;
  627.             }
  628.             return ($puroEstimation['date']->format('W') < $bestEstimation['date']->format('W')) ? $puroEstimation $bestEstimation;
  629.         }
  630.         return [
  631.             'date' => $this->getDistrubutorMaintenanceEstimationShippingForProduct($product,$todaysDate),
  632.             'route' => null
  633.         ];
  634.     }
  635.     public function getYMDFromDateObject($deliveryDate) {
  636.       return $deliveryDate->format("Y-m-d");
  637.     }
  638.     public function getIsDeliveredByDeliveryDate($deliveryDate) {
  639.       $delivery_stop = new \DateTime($deliveryDate->format("Y-m-d 21:00:00"), new \DateTimeZone("America/New_York"));
  640.       $timestamp_delivery_stop $delivery_stop->format("U");
  641.       $now time();
  642.       if (
  643.         $now >= $timestamp_delivery_stop
  644.       ) {
  645.         return true;
  646.       } else {
  647.         return false;
  648.       }
  649.     }
  650.     public function getMaintenanceEstimationShippingForMaturinProducts($cart){
  651.         if ($cart->getDatePayment()) {
  652.         $late = clone $cart->getDatePayment();
  653.         $cartPaymentDate = clone $late;
  654.         foreach($cart->getProducts() as $p){
  655.             $est $this->getMaintenanceEstimationShippingRoute($p->getProduct(),$cartPaymentDate)['date'];
  656.             if($est $late)
  657.                 $late $est;
  658.         }}
  659.         return $late;
  660.     }
  661.     public function getDistrubutorMaintenanceEstimationShippingForProduct(Product $product,\DateTime $date)
  662.     {
  663.         //@Notes reminder of weekday per PHP doc just easier to read
  664.         $weekDayLabel = [
  665.             'Sunday' => 0,
  666.             'Monday' => 1,
  667.             'Tuesday' => 2,
  668.             'Wednesday' => 3,
  669.             'Thursday' => 4,
  670.             'Friday' => 5,
  671.             'Saturday' => 6
  672.         ];
  673.         $now $date;
  674.         $weekDay $now->format('w');
  675.         $hour $now->format('G');
  676.         //JIT product with past delivery time
  677.         if($product->getIsJustinTime() && !empty($product->getJustInTimeDeliveryDate())){
  678.             return $product->getJustInTimeDeliveryDate();
  679.         }
  680.         //if($product->getCompany()->getId() == 181 || $product->getIsJustInTime()){
  681.         if($product->getCompany()->getId() == 181 ){
  682.             return $date->modify("next week friday");
  683.         }
  684.         if($product->getIsJustinTime())
  685.             return $date->modify("next week friday");
  686.         //return new \DateTime("+6 weekdays");
  687.         //If it's a froozen product we ship until wednesday only
  688.         $froozenDays = array($weekDayLabel['Thursday'], $weekDayLabel['Friday'], $weekDayLabel['Saturday'], $weekDayLabel['Sunday']);
  689.         if($product->getIsFroozen() && in_array($weekDay,$froozenDays)){
  690.             return $date->modify("next thursday");
  691.         }
  692.         //We manage and overwrite Solex Estimation date
  693.         if($product->getIsJustinTime()){
  694.             //If we tuesday or past tuesday, order should be received next thursday
  695.             if($weekDay $weekDayLabel['Monday']){
  696.                 if($weekDay <= $weekDayLabel['Thursday'])
  697.                     $estimationDate $date->modify("thursday next week");
  698.                 else
  699.                     $estimationDate $date->modify("next thursday");
  700.                 return $estimationDate;
  701.             }else
  702.                 return $date->modify("thursday");
  703.         }
  704.         if($weekDay == $weekDayLabel['Friday'])
  705.             return $date->modify("next tuesday");
  706.         if($hour <= 11 )
  707.             return $date->modify("+48 hours");
  708.         return $date->modify("+72 hours");
  709.     }
  710.     public function getReusableBoxProduct(){
  711.         $reusableBoxId=6472;
  712.         return $this->em->getRepository(Product::class)->findOneBy(['id' => $reusableBoxId]);
  713.     }
  714.      //fecth and update track pod order status
  715.     public function updateGoColisOrderStatus($order){
  716.         //dont call the APi service if order has been delivered
  717.         if($order->getTrackPodStatusId()== || $order->isShippedLegacy()){
  718.             return true;
  719.         }
  720.         $this->trackPodServ->updateOrder($order);
  721.         return true;
  722.     }
  723.     /*
  724.      * Return a boolean if we display the survey or no
  725.      */
  726.     public function getDisplaySurvey()
  727.     {
  728.         if($this->getStarterKits()){
  729.             $user=$this->userServ->getUser();
  730.             //Not a loggued user we dont display
  731.             if(!$user){
  732.                 return false;
  733.             }
  734.             if($user->getDontShowSurvey()){
  735.                 return false;
  736.             }
  737.             //If the user do not have the survey filled we display
  738.             if(empty($this->userServ->getUser()->getUserSurvey())){
  739.                 if($user->getNextUserSurveyTime()){
  740.                     $date = new DateTime();
  741.                     if($date $user->getNextUserSurveyTime() ){
  742.                         return false;
  743.                     }
  744.                 }
  745.                 return true;
  746.             }
  747.         }
  748.         return false;
  749.     }
  750.     public function getCountProduct($category)
  751.     {
  752.         $countProduct $this->em->getRepository(Product::class)->getcategoriesByPlacement($categorynullnull);
  753.         return count($countProduct);
  754.     }
  755.     public function getTheProduct($id)
  756.     {
  757.         $product $this->em->getRepository(Product::class)->findOneBy(["id" => $id]);
  758.         return $product;
  759.     }
  760.     public function  getTheCategoryProduct($id)
  761.     {
  762.         $category $this->em->getRepository(Category::class)->findOneBy(["id" => $id]);
  763.         
  764.         return $category;
  765.     }
  766.     public function getQuantityJitThisWeek($id)
  767.     {
  768.         $product $this->em->getRepository(Product::class)->findOneBy(["id" => $id]);
  769.         $qtyWeeklySoldForProduct $this->em->getRepository(CartProduct::class)->findWeeklyAlreadySoldForProductJit($id);
  770.         if (!$qtyWeeklySoldForProduct) {$qtyWeeklySoldForProduct 0;}
  771.           $getQtyReadyToShip $product->getQtyReadyToShip();
  772.           if ($getQtyReadyToShip) {
  773.             if($qtyWeeklySoldForProduct $getQtyReadyToShip ) { 
  774.                  return false;
  775.             }else{
  776.                 return true;
  777.             }
  778.         }
  779.     }
  780.     
  781. }