src/Repository/Booking/QuoteRepository.php line 37

Open in your IDE?
  1. <?php
  2. namespace App\Repository\Booking;
  3. use App\DBAL\Types\Account\WebQuoteStepEnum;
  4. use App\DBAL\Types\Booking\BookingStep;
  5. use App\DBAL\Types\Booking\Cabin\CabinStepEnum;
  6. use App\Entity\__Contact\contact\Contact;
  7. use App\Entity\Booking\Booking;
  8. use App\Entity\Booking\Quote;
  9. use App\Entity\ParameterCodes;
  10. use App\Entity\User\User;
  11. use App\Migration\Entity\CsvQuote;
  12. use App\Repository\Email\EmailContentRepository;
  13. use App\Voter\QuoteVoter;
  14. use Crea\SecurityBundle\Helper\AccessHelper;
  15. use Crea\SecurityBundle\Model\Access;
  16. use DateTime;
  17. use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
  18. use Doctrine\ORM\NonUniqueResultException;
  19. use Doctrine\ORM\QueryBuilder;
  20. use Doctrine\Persistence\ManagerRegistry;
  21. use Exception;
  22. use Symfony\Component\Security\Core\Security;
  23. /**
  24.  * @method Quote|null find($id, $lockMode = null, $lockVersion = null)
  25.  * @method Quote|null findOneBy(array $criteria, array $orderBy = null)
  26.  * @method Quote[]    findAll()
  27.  * @method Quote[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
  28.  */
  29. class QuoteRepository extends ServiceEntityRepository
  30. {
  31.     protected Security $security;
  32.     protected AccessHelper $accessHelper;
  33.     public function __construct(ManagerRegistry $registry,
  34.                                 Security        $security,
  35.                                 AccessHelper    $accessHelper)
  36.     {
  37.         parent::__construct($registryQuote::class);
  38.         $this->security $security;
  39.         $this->accessHelper $accessHelper;
  40.     }
  41.     public const QUOTE_NUMBER_PREFIX 'DEV';
  42.     public const QUOTE_CONVERTER_B2B 'B2B';
  43.     public const QUOTE_CONVERTER_FULLWEB 'FULLWEB';
  44.     public const QUOTE_CONVERTER_MANUAL 'MANUAL';
  45.     
  46.     public const QUOTE_ORIGIN_ERP 'erp';
  47.     public const QUOTE_ORIGIN_CMS 'cms';
  48.     public function getGridQueryBuilderQuotesWithNotConfirmedOption(): QueryBuilder
  49.     {
  50.         return $this->createQueryBuilder('q')
  51.             ->join('q.booking''b')
  52.             ->join('q.cabins''c')
  53.             ->andWhere('q.webQuoteStep IN (:insurance, :summary, :payment)')
  54.             ->andWhere('b.step = :notBooked')
  55.             ->andWhere('c.step = :option')
  56.             ->andWhere('q.converter IS NOT NULL')
  57. //            ->andWhere('q.converter != :manual')
  58.             ->setParameters([
  59.                 'insurance' => WebQuoteStepEnum::INSURANCE,
  60.                 'summary' => WebQuoteStepEnum::SUMMARY,
  61.                 'payment' => WebQuoteStepEnum::PAYMENT,
  62.                 'notBooked' => BookingStep::NOT_BOOKED,
  63.                 'option' => CabinStepEnum::OPTION,
  64. //                'manual' => QuoteManager::MANUAL,
  65.                 ])
  66.             ;
  67.     }
  68.     public function getGridQueryBuilderQuotesWithConfirmedOption(): QueryBuilder
  69.     {
  70.         return $this->createQueryBuilder('q')
  71.             ->andWhere('q.quoteValidityAt > :now')
  72.             ->andWhere('q.converter IN (:fullWeb)')
  73.             ->setParameters([
  74.                 'fullWeb' => self::QUOTE_CONVERTER_FULLWEB,
  75.                 'now' => new DateTime(),
  76.             ]);
  77.     }
  78.     public function getGridQueryBuilderQuotesWithOptionInProgress(): QueryBuilder
  79.     {
  80.         $qb $this->createQueryBuilder('q')
  81.             ->andWhere('q.quoteValidityAt > :now')
  82.             ->setParameters([
  83.                 'now' => new DateTime(),
  84.             ]);
  85.         if (!$this->accessHelper->hasAccess(new Access([QuoteVoter::OPTION_IN_PROGRESS_SHOW_ALL_SELLERS]))) {
  86.             /** @var User $user */
  87.             $user $this->security->getUser();
  88.             $qb $qb
  89.                 ->join('q.seller''u')
  90.                 ->andWhere($qb->expr()->eq('u.id'$user->getId()));
  91.         }
  92.         return $qb;
  93.     }
  94.     public function getGridQueryBuilderQuotes(): QueryBuilder
  95.     {
  96.         $qb $this->createQueryBuilder('q');
  97.         if (!$this->accessHelper->hasAccess(new Access([QuoteVoter::SHOW_ALL_SELLERS]))) {
  98.             /** @var User $user */
  99.             $user $this->security->getUser();
  100.             $qb $qb
  101.                 ->join('q.seller''u')
  102.                 ->andWhere($qb->expr()->eq('u.id'$user->getId()));
  103.         }
  104.         return $qb;
  105.     }
  106.     public function findQuotesWithOptionInProgress(?User $user null): array
  107.     {
  108.         $qb $this->createQueryBuilder('q');
  109.         $qb $qb
  110.             ->andWhere($qb->expr()->gte('q.quoteValidityAt'':now'))
  111.             ->setParameter('now', new DateTime());
  112.         if ($user !== null) {
  113.             $qb $qb
  114.                 ->join('q.seller''u')
  115.                 ->andWhere($qb->expr()->eq('u.id'$user->getId()));
  116.         }
  117.         return $qb
  118.             ->getQuery()
  119.             ->getResult();
  120.     }
  121.     /**
  122.      * @throws NonUniqueResultException
  123.      */
  124.     public function findProcessQuote(int $id): ?Quote
  125.     {
  126.         return $this
  127.             ->createQueryBuilder('q')
  128.             ->innerJoin('q.cruiseHistory''ch')
  129.             ->innerJoin('ch.itineraryHistory''ih')
  130.             ->leftJoin('q.cabinCategoryHistory''cch')
  131.             ->leftJoin('q.participants''qp')
  132.             ->leftJoin('qp.passengerInformation''qpi')
  133.             ->leftJoin('qp.cabin''ca')
  134.             ->leftJoin('q.quoteLines''ql')
  135.             ->select('q''ch''ih''cch''qp''qpi''ca''ql')
  136.             ->where('q.id = :id')
  137.             ->andWhere('ch.isCurrent = :cruiseHistoryIsCurrent')
  138.             ->setParameters(['id' => $id'cruiseHistoryIsCurrent' => true])
  139.             ->getQuery()
  140.             ->getOneOrNullResult();
  141.     }
  142.     /**
  143.      * @param Contact $contact
  144.      * @return array|Quote[]
  145.      */
  146.     public function getContactQuotes(Contact $contact): array
  147.     {
  148.         return $this->createQueryBuilder('q')
  149.             ->andWhere('q.contact = :contact')
  150.             ->setParameters(['contact' => $contact])
  151.             ->orderBy('q.id''DESC')
  152.             ->getQuery()
  153.             ->getResult();
  154.     }
  155. //    public function getContactExpiredQuotes(Contact $contact): array
  156. //    {
  157. //        return $this->createQueryBuilder('q')
  158. //            ->andWhere('q.contact = :contact')
  159. //            ->andWhere('q.webQuoteStep = :steps')
  160. //            ->setParameters(['contact' => $contact, 'steps' => ParameterCodes::QUOTE_STATUS_DEADLINE_OVER])
  161. //            ->orderBy('q.id', 'DESC')
  162. //            ->getQuery()
  163. //            ->getResult();
  164. //    }
  165. //
  166. ////    permet de trouver le dernier quote ayant un numéro commençant par DEV
  167. //
  168. //    /**
  169. //     * @throws NonUniqueResultException
  170. //     */
  171. //    public function findLastQuoteWithNumber(): ?Quote
  172. //    {
  173. //        return $this->createQueryBuilder('q')
  174. //            ->andWhere('q.number IS NOT NULL')
  175. //            ->andWhere('q.number like :number')
  176. //            ->setParameter('number', self::QUOTE_NUMBER_PREFIX.'%')
  177. //            ->orderBy('CAST(REPLACE(q.number, \''.self::QUOTE_NUMBER_PREFIX.'\',  \'\') AS UNSIGNED)', 'DESC')
  178. //            ->setMaxResults(1)
  179. //            ->getQuery()
  180. //            ->getOneOrNullResult();
  181. //    }
  182. //
  183. ////    retourne les devis vente de contingents ($contigent = true), ou la liste des devis vente classique ($contingent = false)
  184. //    public function getContingentBooking(Booking $booking, bool $contingent): array
  185. //    {
  186. //        return $this->createQueryBuilder('q')
  187. //            ->where('q.contingent = :con')
  188. //            ->andWhere('q.booking = :booking')
  189. //            ->setParameters(['con' => $contingent, 'booking' => $booking])
  190. //            ->getQuery()
  191. //            ->getResult();
  192. //    }
  193. //
  194. //    /**
  195. //     * Récupère le nombre de devis qui a un lien avec une demande de prospect.
  196. //     *
  197. //     * @param null|User|array $statsFrom
  198. //     * @throws Exception
  199. //     */
  200. //    public function findConvertedQuoteNumber($statsFrom = null): int
  201. //    {
  202. //        if (!($statsFrom instanceof User) && !is_array($statsFrom) && null !== $statsFrom) {
  203. //            throw new Exception('Error: the parameter should be one of the following instance: User, array, null. ' . get_class($statsFrom) . ' given.');
  204. //        }
  205. //
  206. //        $queryBuilder = $this->createQueryBuilder('q')
  207. //            ->select('COUNT(q.id)')
  208. //            ->where('q.prospectRequest IS NOT NULL')
  209. //        ;
  210. //
  211. //        if ($statsFrom instanceof User) {
  212. //            $queryBuilder
  213. //                ->join('q.prospectRequest', 'p')
  214. //                ->andWhere('p.assignedUser = :user')
  215. //                ->setParameter('user', $statsFrom)
  216. //            ;
  217. //        } elseif (is_array($statsFrom)) {
  218. //            $queryBuilder
  219. //                ->join('q.prospectRequest', 'p')
  220. //                ->andWhere('p.assignedUser in (:users)')
  221. //                ->setParameter('users', $statsFrom)
  222. //            ;
  223. //        }
  224. //
  225. //        return $queryBuilder
  226. //            ->getQuery()
  227. //            ->getSingleScalarResult()
  228. //        ;
  229. //    }
  230. //
  231. //    /**
  232. //     * Récupère le nombre de devis Ã  l'état non réservé qui a un lien avec une demande de prospect, elle-même liée Ã  un contact.
  233. //     *
  234. //     * @param null|User|array $statsFrom
  235. //     * @throws Exception
  236. //     */
  237. //    public function findContactRequestConvertedToQuoteNumber($statsFrom = null): int
  238. //    {
  239. //        if (!($statsFrom instanceof User) && !is_array($statsFrom) && null !== $statsFrom) {
  240. //            throw new Exception('Error: the parameter should be one of the following instance: User, array, null. ' . get_class($statsFrom) . ' given.');
  241. //        }
  242. //
  243. //        $queryBuilder = $this->createQueryBuilder('q')
  244. //            ->select('COUNT(q.id)')
  245. //            ->join('q.prospectRequest', 'p')
  246. //            ->join('q.booking', 'b')
  247. //            ->where('p.contact IS NOT NULL')
  248. //            ->andWhere('b.step in (:steps)')
  249. //        ;
  250. //
  251. //        $parameters = ['steps' => [BookingStep::NOT_BOOKED]];
  252. //
  253. //        if ($statsFrom instanceof User) {
  254. //            $queryBuilder->andWhere('p.assignedUser = :user');
  255. //            $parameters['user'] = $statsFrom;
  256. //        } elseif (is_array($statsFrom)) {
  257. //            $queryBuilder->andWhere('p.assignedUser in (:users)');
  258. //            $parameters['users'] = $statsFrom;
  259. //        }
  260. //
  261. //        return $queryBuilder
  262. //            ->setParameters($parameters)
  263. //            ->getQuery()
  264. //            ->getSingleScalarResult()
  265. //        ;
  266. //    }
  267. //
  268. //    /**
  269. //     * Récupère le nombre de devis Ã  l'état réservé qui a un lien avec une demande de prospect, elle-même liée Ã  un contact.
  270. //     *
  271. //     * @param null|User|array $statsFrom
  272. //     * @throws Exception
  273. //     */
  274. //    public function findContactRequestConvertedToBookingNumber($statsFrom = null): int
  275. //    {
  276. //        if (!($statsFrom instanceof User) && !is_array($statsFrom) && null !== $statsFrom) {
  277. //            throw new Exception('Error: the parameter should be one of the following instance: User, array, null. ' . get_class($statsFrom) . ' given.');
  278. //        }
  279. //
  280. //        $queryBuilder = $this->createQueryBuilder('q')
  281. //            ->select('COUNT(q.id)')
  282. //            ->join('q.prospectRequest', 'p')
  283. //            ->join('q.booking', 'b')
  284. //            ->where('p.contact IS NOT NULL')
  285. //            ->andWhere('b.step in (:steps)')
  286. //        ;
  287. //
  288. //        $parameters = ['steps' => [BookingStep::ACCOUNT_PAID, BookingStep::FULLY_PAID]];
  289. //
  290. //        if ($statsFrom instanceof User) {
  291. //            $queryBuilder->andWhere('p.assignedUser = :user');
  292. //            $parameters['user'] = $statsFrom;
  293. //        } elseif (is_array($statsFrom)) {
  294. //            $queryBuilder->andWhere('p.assignedUser in (:users)');
  295. //            $parameters['users'] = $statsFrom;
  296. //        }
  297. //
  298. //        return $queryBuilder
  299. //            ->setParameters($parameters)
  300. //            ->getQuery()
  301. //            ->getSingleScalarResult()
  302. //        ;
  303. //    }
  304. //
  305. //    /**
  306. //     * Récupère le nombre de devis créé par utilisateur.
  307. //     */
  308. //    public function countCreatedQuoteByUser(array $users): array
  309. //    {
  310. //        return $this->createQueryBuilder('q')
  311. //            ->select('COUNT(q.id) as number, u.id as sellerId, u.firstName as sellerFirstName, u.lastName as sellerLastName')
  312. //            ->join('q.seller', 'u')
  313. //            ->where('u.id in (:users)')
  314. //            ->setParameter('users', $users)
  315. //            ->groupBy('u.id')
  316. //            ->getQuery()
  317. //            ->getResult()
  318. //        ;
  319. //    }
  320.     public function findExpiredQuotes(?array $companyCodes null): array
  321.     {
  322.         $qb $this->createQueryBuilder('q')
  323.             ->innerJoin('q.cruiseHistory''ch')
  324.             ->innerJoin('ch.ship''s')
  325.             ->innerJoin('s.company''c');
  326.         $qb->where($qb->expr()->isNotNull('q.quoteValidityAt'))
  327.             ->andWhere($qb->expr()->lt('q.quoteValidityAt'':now'))
  328.             ->andWhere($qb->expr()->isNull('q.booking'));
  329.         $parameters = ['now' => new DateTime()];
  330.         if ($companyCodes !== null) {
  331.             $qb->andWhere($qb->expr()->in('c.code'':companyCodes'));
  332.             $parameters["companyCodes"] = $companyCodes;
  333.         }
  334.         return $qb->setParameters($parameters)
  335.             ->getQuery()
  336.             ->getResult();
  337.     }
  338.     public function findNoTransformedQuotes8HoursBeforeExpiration(): array
  339.     {
  340.         $qb $this->createQueryBuilder('q')
  341.             ->innerJoin('q.attributedSentEmails''ase')
  342.             ->innerJoin('ase.sentEmail''se')
  343.             ->innerJoin('se.email''e')
  344.             ->innerJoin('e.emailContent''ec');
  345.         $qb->where($qb->expr()->isNotNull('q.quoteValidityAt'))
  346.             ->andWhere($qb->expr()->gt('q.quoteValidityAt'':now8Hours'))
  347.             ->andWhere($qb->expr()->lte('q.quoteValidityAt'':now9Hours'))
  348.             ->andWhere($qb->expr()->in('ec.code'':codes'))
  349.             ->setParameters([
  350.                 'now8Hours' => (new DateTime())->modify('+8 hour')->format("Y-m-d H:i:s"),
  351.                 'now9Hours' => (new DateTime())->modify('+9 hour')->format("Y-m-d H:i:s"),
  352.                 'codes' => [EmailContentRepository::SEND_QUOTE_NEW_BOOKING_CODEEmailContentRepository::SEND_QUOTE_NEW_BOOKING_WITH_CREDIT_CODE],
  353.             ])
  354.             ->groupBy('q.id');
  355.         return $qb->getQuery()
  356.             ->getResult();
  357.     }
  358. //    /**
  359. //     * @param QueryBuilder $qb
  360. //     * @param $start
  361. //     * @param $end
  362. //     */
  363. //    private function currentDateFullWebQuotes(QueryBuilder $qb, $start, $end): void
  364. //    {
  365. //        $qb
  366. //            ->andWhere('q.createdAt BETWEEN :start AND :end')
  367. //            ->andWhere('q.converter = :fullWeb')
  368. //            ->setParameters([
  369. //                'fullWeb' => self::QUOTE_CONVERTER_FULLWEB,
  370. //                'start' => $start,
  371. //                'end' =>   $end,
  372. //            ])
  373. //        ;
  374. //    }
  375. //
  376. //    /**
  377. //     * @throws Exception
  378. //     *  @return Quote[] Returns an array of Quote objects
  379. //     */
  380. //    public function getCurrentYearFullWebQuotes(): array
  381. //    {
  382. //        $qb = $this->createQueryBuilder('q');
  383. //        $start = new Datetime(date('Y').'-01-01');
  384. //        $end = new Datetime(date('Y').'-12-31');
  385. //
  386. //        $this->currentDateFullWebQuotes($qb, $start, $end);
  387. //
  388. //        return $qb
  389. //            ->getQuery()
  390. //            ->getResult()
  391. //            ;
  392. //    }
  393. //
  394. //    /**
  395. //     * @throws Exception
  396. //     *  @return Quote[] Returns an array of Quote objects
  397. //     */
  398. //    public function getCurrentWeekFullWebQuotes(): array
  399. //    {
  400. //        $qb = $this->createQueryBuilder('q');
  401. //
  402. //        if( date('D') != 'Mon' ) {
  403. //            $lastMonday = date('Y-m-d 00:00',strtotime('last monday'));
  404. //        }else {
  405. //            $lastMonday = date('Y-m-d 00:00');
  406. //        }
  407. //
  408. //        $start = new Datetime($lastMonday);
  409. //        $end = (clone $start)->modify('+ 6 days');
  410. //
  411. //        $this->currentDateFullWebQuotes($qb, $start, $end);
  412. //
  413. //        return $qb
  414. //            ->getQuery()
  415. //            ->getResult()
  416. //            ;
  417. //    }
  418. //
  419. //    /**
  420. //     * @throws Exception
  421. //     *  @return Quote[] Returns an array of Quote objects
  422. //     */
  423. //    public function getCurrentDayFullWebQuotes(): array
  424. //    {
  425. //        $qb = $this->createQueryBuilder('q');
  426. //        $start = new Datetime(date('Y-m-d 00:00'));
  427. //        $end = new Datetime(date('Y-m-d h:i'));
  428. //
  429. //        $this->currentDateFullWebQuotes($qb, $start, $end);
  430. //
  431. //        return $qb
  432. //            ->getQuery()
  433. //            ->getResult()
  434. //            ;
  435. //    }
  436. //
  437. //    /**
  438. //     * @return QueryBuilder
  439. //     */
  440. //    public function getQuotesInReviewQueryBuilder(): QueryBuilder
  441. //    {
  442. //        return $this->createQueryBuilder('q')
  443. //            ->innerJoin('q.attributedSentEmails', 'emails')
  444. //            ->innerJoin('q.stateType', 'qst')
  445. //            ->andWhere('emails.sentEmail IS NOT NULL')
  446. //            ->andWhere('qst.code = :code')
  447. //            ->setParameters([
  448. //                'code' => ParameterCodes::QUOTE_STATUS_REVIEW,
  449. //            ]);
  450. //    }
  451. //
  452. //    /**
  453. //     * @return Quote[] Returns an array of Quote objects
  454. //     */
  455. //    public function getQuotesInReviewAndSend(): array
  456. //    {
  457. //        return $this->getQuotesInReviewQueryBuilder()
  458. //            ->getQuery()
  459. //            ->getResult()
  460. //            ;
  461. //    }
  462. //
  463. //    /**
  464. //     * @return Quote[] Returns an array of Quote objects
  465. //     */
  466. //    public function getQuotesInReviewAndSendBySeller(array $sellers): array
  467. //    {
  468. //        return $this->createQueryBuilder('q')
  469. //            ->innerJoin('q.attributedSentEmails', 'emails')
  470. //            ->innerJoin('q.stateType', 'qst')
  471. //            ->andWhere('emails.sentEmail IS NOT NULL')
  472. //            ->andWhere('qst.code = :code')
  473. //            ->innerJoin('q.seller', 's')
  474. //            ->andWhere('s.id in (:sellers)')
  475. //            ->select('COUNT(q) as number, MIN(q.createdAt) as date, s.firstName as sellerFirstName, s.lastName as sellerLastName')
  476. //            ->groupBy('s')
  477. //            ->setParameters([
  478. //                'sellers' => $sellers,
  479. //                'code' => ParameterCodes::QUOTE_STATUS_REVIEW,
  480. //            ])
  481. //            ->getQuery()
  482. //            ->getResult()
  483. //            ;
  484. //    }
  485. //
  486. //    /**
  487. //     * @throws Exception
  488. //     *  @return Quote[] Returns an array of Quote objects
  489. //     */
  490. //    public function getQuotesWithCroisilandOptionInProgressBySeller(array $sellers): array
  491. //    {
  492. //        return $this->createQueryBuilder('q')
  493. //            ->andWhere('q.quoteValidityAt = :now')
  494. //            ->innerJoin('q.seller', 's')
  495. //            ->join('q.contact', 'c')
  496. //            ->join('q.stateType', 'qst')
  497. //            ->andWhere('c.isActive = :isActive')
  498. //            ->andWhere('qst.code = :code')
  499. //            ->andWhere('s.id in (:sellers)')
  500. //            ->select('COUNT(q.id) as number, s.firstName as sellerFirstName, s.lastName as sellerLastName')
  501. //            ->groupBy('s')
  502. //            ->setParameters([
  503. //                'now' => new DateTime(),
  504. //                'code' => ParameterCodes::QUOTE_STATUS_REVIEW,
  505. //                'isActive' => true,
  506. //                'sellers' => $sellers,
  507. //            ])
  508. //            ->getQuery()
  509. //            ->getResult()
  510. //            ;
  511. //    }
  512. //
  513. //
  514. //    /**
  515. //     * @return Quote[]
  516. //     */
  517. //    public function getQuotesWithoutCsvRelation(): array
  518. //    {
  519. //        $qb = $this->createQueryBuilder('q')
  520. //            ->leftJoin(CsvQuote::class, 'cq', 'WITH', 'cq.tdevisId = q.oldCrmId');
  521. //        return $qb
  522. //            ->where($qb->expr()->isNull('cq.id'))
  523. //            ->getQuery()
  524. //            ->getResult();
  525. //    }
  526.     /********************************* home-module *************************************/
  527.     public function countThisDateQuotes(DateTime $date, ?User $user null): int
  528.     {
  529.         $qb $this->createQueryBuilder('q')
  530.             ->select('count(q.id)');
  531.         $qb $qb
  532.             ->where($qb->expr()->gt('q.createdAt'':date'))
  533.             ->setParameter('date'$date);
  534.         if ($user !== null) {
  535.             $qb $qb
  536.                 ->join('q.seller''u')
  537.                 ->andWhere($qb->expr()->eq('u.id'$user->getId()));
  538.         }
  539.         return $qb
  540.             ->getQuery()
  541.             ->getSingleScalarResult()
  542.         ;
  543.     }
  544.     public function countAllQuotes(?User $user null): int
  545.     {
  546.         $qb $this->createQueryBuilder('q')
  547.             ->select('count(q.id)');
  548.         if ($user !== null) {
  549.             $qb $qb
  550.                 ->join('q.seller''u')
  551.                 ->where($qb->expr()->eq('u.id'$user->getId()));
  552.         }
  553.         return $qb
  554.             ->getQuery()
  555.             ->getSingleScalarResult()
  556.         ;
  557.     }
  558.     public function countConversionQuotesThisDate(DateTime $date, ?User $user null): int
  559.     {
  560.         $qb $this->createQueryBuilder('q');
  561.         $qb $qb
  562.             ->select('count(q.id)')
  563.             ->where($qb->expr()->gt('q.createdAt'':date'))
  564.             ->andWhere($qb->expr()->eq('q.stateType'':code'))
  565.             ->setParameter('date'$date)
  566.             ->setParameter('code'ParameterCodes::QUOTE_STATUS_CONFIRM);
  567.         if ($user !== null) {
  568.             $qb $qb
  569.                 ->join('q.seller''u')
  570.                 ->andWhere($qb->expr()->eq('u.id'$user->getId()));
  571.         }
  572.         return $qb
  573.             ->getQuery()
  574.             ->getSingleScalarResult()
  575.         ;
  576.     }
  577.     public function countAllConversionQuotes(?User $user null): int
  578.     {
  579.         $qb $this->createQueryBuilder('q');
  580.         $qb $qb
  581.             ->select('count(q.id)')
  582.             ->join('q.stateType''qst')
  583.             ->where($qb->expr()->eq('qst.code'':code'))
  584.             ->setParameter('code'ParameterCodes::QUOTE_STATUS_CONFIRM);
  585.         if ($user !== null) {
  586.             $qb $qb
  587.                 ->join('q.seller''u')
  588.                 ->andWhere($qb->expr()->eq('u.id'$user->getId()));
  589.         }
  590.         return $qb
  591.             ->getQuery()
  592.             ->getSingleScalarResult()
  593.         ;
  594.     }
  595.     /**
  596.      * @param Contact $contact
  597.      * @param QueryBuilder|null $queryBuilder
  598.      * @return QueryBuilder
  599.      */
  600.     private function getContactQuoteBaseQueryBuilder(Contact $contact, ?QueryBuilder $queryBuilder null): QueryBuilder
  601.     {
  602.         if ($queryBuilder === null) {
  603.             $queryBuilder $this->createQueryBuilder('q');
  604.         }
  605.         else {
  606.             $queryBuilder $queryBuilder->from(Quote::class, 'q');
  607.         }
  608.         return $queryBuilder
  609.             ->select('q')
  610.             ->join('q.contact''c')
  611.             ->join('q.stateType''qst')
  612.             ->leftJoin('q.quoteReasonStatus''qrs')
  613.             ->leftJoin('q.booking''b')
  614.             ->leftJoin('q.cruiseHistory''cr')
  615.             ->leftJoin('cr.ship''s')
  616.             ->leftJoin('s.company''co')
  617.             ->andWhere($queryBuilder->expr()->eq('c.id'$contact->getId()));
  618.     }
  619.     /**
  620.      * @param Contact $contact
  621.      * @param QueryBuilder|null $queryBuilder
  622.      * @return QueryBuilder
  623.      */
  624.     public function getContactQuoteInProgressQueryBuilder(Contact $contact, ?QueryBuilder $queryBuilder null): QueryBuilder
  625.     {
  626.         $queryBuilder $this->getContactQuoteBaseQueryBuilder($contact$queryBuilder);
  627.         return $queryBuilder
  628.             ->andWhere($queryBuilder->expr()->andX(
  629.                 $queryBuilder->expr()->gte('q.quoteValidityAt'':now'),
  630.                 $queryBuilder->expr()->isNotNull('q.quoteValidityAt')
  631.             ))
  632.             ->andWhere($queryBuilder->expr()->isNull('b.id'))
  633.             ->setParameter('now', new DateTime());
  634.     }
  635.     /**
  636.      * @param Contact $contact
  637.      * @param QueryBuilder|null $queryBuilder
  638.      * @return QueryBuilder
  639.      */
  640.     public function getContactPastQuoteQueryBuilder(Contact $contact, ?QueryBuilder $queryBuilder null): QueryBuilder
  641.     {
  642.         $queryBuilder $this->getContactQuoteBaseQueryBuilder($contact$queryBuilder);
  643.         return $queryBuilder
  644.             ->andWhere(
  645.                 $queryBuilder->expr()->orX(
  646.                     $queryBuilder->expr()->andX(
  647.                         $queryBuilder->expr()->lt('q.quoteValidityAt'':now'),
  648.                         $queryBuilder->expr()->isNotNull('q.quoteValidityAt')
  649.                     ),
  650.                     $queryBuilder->expr()->isNotNull('b.id')
  651.                 )
  652.             )
  653.             ->setParameter('now', new DateTime());
  654.     }
  655.     /**
  656.      * Get the list of current quotes for a contact
  657.      *
  658.      * @param Contact $contact
  659.      * @return array
  660.      */
  661.     public function getContactQuoteInProgress(Contact $contact): array
  662.     {
  663.         return $this->getContactQuoteInProgressQueryBuilder($contact)
  664.             ->getQuery()
  665.             ->getResult();
  666.     }
  667.     /**
  668.      * Get the list of past quotes for a contact
  669.      *
  670.      * @param Contact $contact
  671.      * @return array
  672.      */
  673.     public function getContactPastQuote(Contact $contact): array
  674.     {
  675.         return $this->getContactPastQuoteQueryBuilder($contact)
  676.             ->getQuery()
  677.             ->getResult();
  678.     }
  679.     /**
  680.      * Get the list of all quotes for a contact
  681.      *
  682.      * @param Contact $contact
  683.      * @return array
  684.      */
  685.     public function getContactAllQuote(Contact $contact): array
  686.     {
  687.         return $this->getContactQuoteBaseQueryBuilder($contact)
  688.             ->getQuery()
  689.             ->getResult();
  690.     }
  691. }