src/Repository/Booking/ProspectRequestRepository.php line 62

Open in your IDE?
  1. <?php
  2. namespace App\Repository\Booking;
  3. use App\Controller\__Sale\ProspectRequestController;
  4. use App\DBAL\Types\Booking\BookingStep;
  5. use App\Entity\__Contact\contact\Contact;
  6. use App\Entity\Booking\ProspectRequest;
  7. use App\Entity\Contact\Prospect;
  8. use App\Entity\ParameterCodes;
  9. use App\Entity\User\User;
  10. use App\Migration\Entity\CsvProspectRequest;
  11. use App\Repository\User\UserRepository;
  12. use App\Voter\ProspectRequestVoter;
  13. use Crea\ParameterBundle\Entity\Parameter;
  14. use Crea\SecurityBundle\Helper\AccessHelper;
  15. use Crea\SecurityBundle\Model\Access;
  16. use DateTime;
  17. use DateTimeInterface;
  18. use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
  19. use Doctrine\ORM\NonUniqueResultException;
  20. use Doctrine\ORM\NoResultException;
  21. use Doctrine\ORM\QueryBuilder;
  22. use Doctrine\Persistence\ManagerRegistry;
  23. use Exception;
  24. use Symfony\Component\HttpFoundation\RequestStack;
  25. use Symfony\Component\Security\Core\Security;
  26. /**
  27.  * @method ProspectRequest|null find($id, $lockMode = null, $lockVersion = null)
  28.  * @method ProspectRequest|null findOneBy(array $criteria, array $orderBy = null)
  29.  * @method ProspectRequest[]    findAll()
  30.  * @method ProspectRequest[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
  31.  */
  32. class ProspectRequestRepository extends ServiceEntityRepository
  33. {
  34.     const USER_GROUP_CODE_BY_PROSPECT_REQUEST_TYPE = [
  35.         ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT => UserRepository::MARKETING_USER_GROUP_CODE,
  36.         ParameterCodes::PROSPECT_REQUEST_TYPE_QUOTE_REQUEST => UserRepository::SELLER_USER_GROUP_CODE,
  37.         ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT_ADV => UserRepository::BACK_OFFICE_USER_GROUP_CODE
  38.     ];
  39.     const USER_GROUP_CODE_BY_PROSPECT_REQUEST_TYPE_DEFAULT UserRepository::SELLER_USER_GROUP_CODE;
  40.     const NUMBER_OF_REMINDERS_BEFORE_PERMANENT_MUTED 1;
  41.     const STATE_CONFIRMED 'confirmed';
  42.     const STATE_CANCELLED 'cancelled';
  43.     const ANOMALY 'anomaly';
  44.     const CONTACT_TYPE_CLIENT 'CONTACT_TYPE_CLIENT';
  45.     const CONTACT_TYPE_PROSPECT 'CONTACT_TYPE_PROSPECT';
  46.     const CONTACT_TYPE_NEW_CONTACT 'CONTACT_TYPE_NEW_CONTACT';
  47.     protected Security $security;
  48.     protected AccessHelper $accessHelper;
  49.     protected RequestStack $requestStack;
  50.     public function __construct(ManagerRegistry $registry,
  51.                                 Security $security,
  52.                                 AccessHelper $accessHelper,
  53.                                 RequestStack $requestStack)
  54.     {
  55.         parent::__construct($registryProspectRequest::class);
  56.         $this->security $security;
  57.         $this->accessHelper $accessHelper;
  58.         $this->requestStack $requestStack;
  59.     }
  60.     private function getUnassignedRequestsQueryBuilder(string $select): QueryBuilder
  61.     {
  62.         $qb1 $this->createQueryBuilder('pr1');
  63.         $qb1 $qb1
  64.             ->select($select)
  65.             ->join('pr1.status''st1')
  66.             ->andWhere('pr1.assignedUser IS NULL')
  67.             ->andWhere('st1.code = :newStateTypeId')
  68.             ->setParameter('newStateTypeId'ParameterCodes::PROSPECT_REQUEST_STATUS_NOT_ASSIGNED);
  69.         return $qb1;
  70.     }
  71.     public function getUnassignedRequestsQuery(): QueryBuilder
  72.     {
  73.         return $this->getUnassignedRequestsQueryBuilder('pr1');
  74.     }
  75.     private function getRequestsByTypeToAssignBaseQuery(string $typeCodeQueryBuilder $qbstring $pre ''):QueryBuilder
  76.     {
  77.         $qb $qb
  78.             ->join$pre.'pr.type'$pre.'prt')
  79.             ->join$pre.'pr.status'$pre.'prst')
  80.             ->where($qb->expr()->eq($pre.'prt.code'':code'))
  81.             ->andWhere($qb->expr()->in($pre.'prst.code'':statusCodes'))
  82.             ->andWhere($qb->expr()->isNull($pre.'pr.assignedUser'))
  83.             ->andWhere($qb->expr()->eq($pre.'pr.isActive'':isActive'))
  84.             ->andWhere($qb->expr()->eq($pre.'pr.isQuoteSent'':isQuoteSent'))
  85.             ->setParameter('code'$typeCode)
  86.             ->setParameter('statusCodes', [
  87.                 ParameterCodes::PROSPECT_REQUEST_STATUS_NOT_ASSIGNED
  88.             ])
  89.             ->setParameter('isActive'true)
  90.             ->setParameter('isQuoteSent'false);
  91.         return $qb;
  92.     }
  93.     private function getRequestsByTypeBaseQuery(string $typeCodeQueryBuilder $qbstring $pre ''):QueryBuilder
  94.     {
  95.         $qb $qb
  96.             ->join$pre.'pr.type'$pre.'prt')
  97.             ->where($qb->expr()->eq($pre.'prt.code'':code'))
  98.             ->andWhere($qb->expr()->eq($pre.'pr.isActive'':isActive'))
  99.             ->setParameter('code'$typeCode)
  100.             ->setParameter('isActive'true);
  101.         if (null !== $state $this->requestStack->getCurrentRequest()->query->get('state')) {
  102.             if ($state === self::STATE_CONFIRMED) {
  103.                 $qb $qb
  104.                     ->innerJoin$pre.'pr.quotes'$pre.'prq')
  105.                     ->innerJoin$pre.'prq.booking'$pre.'prb');
  106.             }
  107.             elseif ($state === self::STATE_CANCELLED) {
  108.                 $qb $qb
  109.                     ->leftJoin$pre.'pr.quotes'$pre.'prq')
  110.                     ->leftJoin$pre.'prq.booking'$pre.'prb')
  111.                     ->andWhere($qb->expr()->andX(
  112.                         $qb->expr()->isNull($pre.'prb.id'),
  113.                         $qb->expr()->lt($pre.'prq.quoteValidityAt'':now')
  114.                     ))
  115.                     ->setParameter('now', new DateTime())
  116.                 ;
  117.             }
  118.         }
  119.         return $qb;
  120.     }
  121.     public function getRequestsByTypeToAssignQuery(string $typeCodebool $groupByProject false): QueryBuilder
  122.     {
  123.         $qb $this->createQueryBuilder('pr');
  124.         $qb $this->getRequestsByTypeToAssignBaseQuery($typeCode$qb);
  125.         if ($groupByProject) {
  126.             $pre 'sub_';
  127.             $qb2 $this->createQueryBuilder($pre.'pr')
  128.                 ->select($pre.'pr.id');
  129.             $qb2 $this->getRequestsByTypeToAssignBaseQuery($typeCode$qb2$pre)
  130.                 ->join$pre.'pr.prospectProject'$pre.'prp')
  131.                 ->groupBy($pre.'prp.id');
  132.             $ids array_map(function ($line) {
  133.                 return $line['id'];
  134.             }, $qb2->getQuery()->getArrayResult());
  135.             if (count($ids) > 0) {
  136.                 $qb->andWhere($qb->expr()->in('pr.id'$ids));
  137.             }
  138.         }
  139.         return $qb;
  140.     }
  141.     public function getRequestsByTypeQuery(string $typeCodebool $groupByProject false$assigned false): QueryBuilder
  142.     {
  143.         $qb $this->createQueryBuilder('pr');
  144.         $qb $this->getRequestsByTypeBaseQuery($typeCode$qb);
  145.         if ($assigned) {
  146.             $qb $qb->innerJoin'pr.assignedUser''u');
  147.         }
  148.         if ($typeCode === ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT) {
  149.             $hasAccess $this->accessHelper->hasAccess(new Access([ProspectRequestVoter::SHOW_CONTACT_REQUESTS_FROM_ALL_USERS]));
  150.         }
  151.         elseif ($typeCode === ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT_ADV) {
  152.             $hasAccess $this->accessHelper->hasAccess(new Access([ProspectRequestVoter::SHOW_ADV_CONTACT_REQUESTS_FROM_ALL_USERS]));
  153.         }
  154.         else {
  155.             $hasAccess $this->accessHelper->hasAccess(new Access([ProspectRequestVoter::SHOW_QUOTE_REQUESTS_FROM_ALL_USERS]));
  156.         }
  157.         if (!$hasAccess) {
  158.             /** @var User $user */
  159.             $user $this->security->getUser();
  160.             $qb $qb
  161.                 ->join('pr.assignedUser''u')
  162.                 ->andWhere($qb->expr()->eq('u.id'$user->getId()));
  163.         }
  164.         if ($groupByProject) {
  165.             $pre 'sub_';
  166.             $qb2 $this->createQueryBuilder($pre.'pr')
  167.                 ->select($pre.'pr.id');
  168.             $qb2 $this->getRequestsByTypeBaseQuery($typeCode$qb2$pre)
  169.                 ->join$pre.'pr.prospectProject'$pre.'prp')
  170.                 ->groupBy($pre.'prp.id');
  171.             if ($assigned) {
  172.                 $qb2 $qb2->innerJoin$pre.'pr.assignedUser'$pre.'u');
  173.             }
  174.             if (!$hasAccess) {
  175.                 /** @var User $user */
  176.                 $user $this->security->getUser();
  177.                 $qb2 $qb2
  178.                     ->join($pre.'pr.assignedUser'$pre.'u')
  179.                     ->andWhere($qb2->expr()->eq($pre.'u.id'$user->getId()));
  180.             }
  181.             $ids array_map(function ($line) {
  182.                 return $line['id'];
  183.             }, $qb2->getQuery()->getArrayResult());
  184.             if (count($ids) > 0) {
  185.                 $qb->andWhere($qb->expr()->in('pr.id'$ids));
  186.             }
  187.         }
  188.         return $qb;
  189.     }
  190.     public function getRequestsByTypeQuoteQuery(): QueryBuilder
  191.     {
  192.         return $this->getRequestsByTypeQuery(ParameterCodes::PROSPECT_REQUEST_TYPE_QUOTE_REQUESTfalsetrue);
  193.     }
  194.     public function getDtBaseQuery(QueryBuilder $qbstring $originstring $typeCodestring $pre ''): QueryBuilder
  195.     {
  196.         $qb $qb
  197.             ->join$pre.'pr.type'$pre.'prt')
  198.             ->leftJoin($pre.'pr.status'$pre.'st')
  199.             ->leftJoin($pre.'pr.statusReason'$pre.'str')
  200.             ->leftJoin($pre.'pr.prospectRequestOrigin'$pre.'pro')
  201.             ->leftJoin($pre.'pr.contactProspect'$pre.'cp')
  202.             ->leftJoin($pre.'cp.contact'$pre.'c')
  203.             ->leftJoin($pre.'c.type'$pre.'cot')
  204.             ->leftJoin($pre.'cp.prospect'$pre.'pros')
  205.             ->leftJoin($pre.'pr.prospectProject'$pre.'pp')
  206.             ->leftJoin($pre.'pr.cruiseHistory'$pre.'ch')
  207.             ->leftJoin($pre.'ch.ship'$pre.'s')
  208.             ->leftJoin($pre.'s.company'$pre.'com')
  209.             ->leftJoin($pre.'ch.itineraryHistory'$pre.'ih')
  210.             ->leftJoin($pre.'ih.destination'$pre.'d')
  211.             ->leftJoin($pre.'pr.cabinCategoryHistory'$pre.'cch')
  212.             ->leftJoin($pre.'cch.type'$pre.'cct')
  213.             ->leftJoin($pre.'cct.cabinType'$pre.'ct')
  214.             ->leftJoin($pre.'pr.partner'$pre.'p')
  215.             ->leftJoin($pre.'c.partnerByContacts'$pre.'pbc')
  216.             ->leftJoin($pre.'pbc.partner'$pre.'p2')
  217.             ->where($qb->expr()->eq($pre.'prt.code'':typeCode'))
  218.             ->andWhere($qb->expr()->eq($pre.'pr.isActive'':isActive'))
  219.             ->andWhere($qb->expr()->eq($pre.'pr.removed'':removed'))
  220.             ->setParameter('typeCode'$typeCode)
  221.             ->setParameter('isActive'true)
  222.             ->setParameter('removed'false);
  223.         if ($origin === ProspectRequestController::ORIGIN_TO_ASSIGN && $typeCode === ParameterCodes::PROSPECT_REQUEST_TYPE_QUOTE_REQUEST) {
  224.             $qb $qb
  225.                 ->andWhere($qb->expr()->in($pre.'st.code'':statusCodes'))
  226.                 ->andWhere($qb->expr()->isNull($pre.'pr.assignedUser'))
  227.                 ->andWhere($qb->expr()->eq($pre.'pr.isQuoteSent'':isQuoteSent'))
  228.                 ->setParameter('statusCodes', [
  229.                     ParameterCodes::PROSPECT_REQUEST_STATUS_NOT_ASSIGNED
  230.                 ])
  231.                 ->setParameter('isQuoteSent'false);
  232.         }
  233.         return $qb;
  234.     }
  235.     public function getDtQuery(QueryBuilder $qbstring $originstring $type, ?int $projectId null): QueryBuilder
  236.     {
  237.         if ($type === ProspectRequestController::TYPE_CONTACT) {
  238.             $typeCode ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT;
  239.             $hasAccess $this->accessHelper->hasAccess(new Access([ProspectRequestVoter::SHOW_CONTACT_REQUESTS_FROM_ALL_USERS]));
  240.         }
  241.         elseif ($type === ProspectRequestController::TYPE_ADV) {
  242.             $typeCode ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT_ADV;
  243.             $hasAccess $this->accessHelper->hasAccess(new Access([ProspectRequestVoter::SHOW_ADV_CONTACT_REQUESTS_FROM_ALL_USERS]));
  244.         }
  245.         else {
  246.             $typeCode ParameterCodes::PROSPECT_REQUEST_TYPE_QUOTE_REQUEST;
  247.             $hasAccess $this->accessHelper->hasAccess(new Access([ProspectRequestVoter::SHOW_QUOTE_REQUESTS_FROM_ALL_USERS]));
  248.         }
  249.         if ($origin === ProspectRequestController::ORIGIN_TO_ASSIGN) {
  250.             $assigned false;
  251.         }
  252.         else {
  253.             $assigned true;
  254.         }
  255.         $qb $this->getDtBaseQuery($qb$origin$typeCode);
  256.         if ($origin === ProspectRequestController::ORIGIN_TO_ASSIGN && $projectId === null) {
  257.             $pre 'sub_';
  258.             $qb2 $this->createQueryBuilder($pre.'pr')
  259.                 ->select($pre.'pr.id');
  260.             $qb2 $this->getDtBaseQuery($qb2$origin$typeCode$pre)
  261.                 ->join$pre.'pr.prospectProject'$pre.'prp')
  262.                 ->groupBy($pre.'prp.id');
  263.             $ids array_map(function ($line) {
  264.                 return $line['id'];
  265.             }, $qb2->getQuery()->getArrayResult());
  266.             if (count($ids) > 0) {
  267.                 $qb->andWhere($qb->expr()->in('pr.id'$ids));
  268.             }
  269.         }
  270.         elseif ($projectId !== null) {
  271.             $qb $qb->innerJoin'pr.prospectProject''prp')
  272.                 ->andWhere($qb->expr()->eq('prp.id'$projectId));
  273.         }
  274.         if ($assigned) {
  275.             $qb $qb
  276.                 ->leftJoin'pr.assignedUser''au')
  277.                 ->andWhere($qb->expr()->orX(
  278.                     $qb->expr()->isNotNull('au.id'),
  279.                     $qb->expr()->eq('st.code'':stCode')
  280.                 ))
  281.                 ->setParameter('stCode'ParameterCodes::PROSPECT_REQUEST_STATUS_DONT_PROCESS);
  282.         }
  283.         else {
  284.             $qb $qb->andWhere($qb->expr()->isNull('pr.assignedUser'));
  285.         }
  286.         if (!$hasAccess) {
  287.             /** @var User $user */
  288.             $user $this->security->getUser();
  289.             $qb $qb
  290.                 ->join('pr.assignedUser''u')
  291.                 ->andWhere($qb->expr()->eq('u.id'$user->getId()));
  292.         }
  293.         return $qb;
  294.     }
  295.     public function getRequestsByTypeContactQuery(bool $groupByProject truebool $assigned true): QueryBuilder
  296.     {
  297.         return $this->getRequestsByTypeQuery(ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT$groupByProject$assigned);
  298.     }
  299.     public function getRequestsByTypeContactAdvQuery(bool $groupByProject true): QueryBuilder
  300.     {
  301.         return $this->getRequestsByTypeQuery(ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT_ADV$groupByProject);
  302.     }
  303.     public function getRequestsByTypeQuoteToAssignQuery(bool $groupByProject true): QueryBuilder
  304.     {
  305.         return $this->getRequestsByTypeToAssignQuery(ParameterCodes::PROSPECT_REQUEST_TYPE_QUOTE_REQUEST$groupByProject);
  306.     }
  307.     public function getRequestsByTypeContactToAssignQuery(bool $groupByProject true): QueryBuilder
  308.     {
  309.         return $this->getRequestsByTypeToAssignQuery(ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT$groupByProject);
  310.     }
  311.     public function getRequestsByTypeContactAdvToAssignQuery(): QueryBuilder
  312.     {
  313.         return $this->getRequestsByTypeToAssignQuery(ParameterCodes::PROSPECT_REQUEST_TYPE_CONTACT_ADV);
  314.     }
  315.     /**
  316.      * @param array $originCodes
  317.      * @param bool $groupByProject
  318.      * @return array|ProspectRequest[]
  319.      */
  320.     public function getRequestsByTypeQuoteToAssign(array $originCodes = [], bool $groupByProject true): array
  321.     {
  322.         $qb $this->getRequestsByTypeQuoteToAssignQuery($groupByProject);
  323.         if (count($originCodes) > 0) {
  324.             $qb $qb->join('pr.prospectRequestOrigin''pro')
  325.                 ->andWhere($qb->expr()->in('pro.code'':originCodes'))
  326.                 ->setParameter('originCodes'$originCodes);
  327.         }
  328.         return $qb
  329.             ->getQuery()
  330.             ->getResult();
  331.     }
  332.     /**
  333.      * @param array $originCodes
  334.      * @param bool $groupByProject
  335.      * @return array|ProspectRequest[]
  336.      */
  337.     public function getRequestsByTypeContactToAssign(array $originCodes = [], bool $groupByProject true): array
  338.     {
  339.         $qb $this->getRequestsByTypeContactToAssignQuery($groupByProject);
  340.         if (count($originCodes) > 0) {
  341.             $qb $qb->join('pr.prospectRequestOrigin''pro')
  342.                 ->andWhere($qb->expr()->in('pro.code'':originCodes'))
  343.                 ->setParameter('originCodes'$originCodes);
  344.         }
  345.         return $qb
  346.             ->getQuery()
  347.             ->getResult();
  348.     }
  349.     /**
  350.      * @param int $projectId
  351.      * @param $unassigned
  352.      * @param $prospectRequestTypeCode
  353.      * @return array|ProspectRequest[]
  354.      */
  355.     public function getProjectRequests(int $projectId$unassigned true$prospectRequestTypeCode null): array
  356.     {
  357.         $qb $this->getProjectRequestQueryBuilder($projectId$unassigned$prospectRequestTypeCode);
  358.         return $qb->getQuery()->getResult();
  359.     }
  360.     public function countProjectRequests(int $projectId$unassigned true$prospectRequestTypeCode null): int
  361.     {
  362.         try {
  363.             $qb $this->getProjectRequestQueryBuilder($projectId$unassigned$prospectRequestTypeCode)->select('count(pr.id)');
  364.             return $qb->getQuery()->getSingleScalarResult();
  365.         }
  366.         catch (NonUniqueResultException|NoResultException $e) {
  367.             return 0;
  368.         }
  369.     }
  370.     /**
  371.      * @param Contact|Prospect $contactOrProspect
  372.      *
  373.      * @return ProspectRequest[]
  374.      */
  375.     public function findContactOrProspectRequestsByDate($contactOrProspectDateTimeInterface $dateParameter $type): array
  376.     {
  377.         $queryBuilder $this->createQueryBuilder('pr')
  378.             ->join('pr.type''pt')
  379.             ->join('pr.contactProspect''cp')
  380.             ->andWhere('DATE_FORMAT(pr.createdAt, \'%Y-%m-%d\') = :date')
  381.             ->setParameter('date'$date->format('Y-m-d'));
  382.         $queryBuilder $queryBuilder
  383.             ->andWhere($queryBuilder->expr()->eq('pt.id'':type'))
  384.             ->setParameter('type'$type->getId());
  385.         if ($contactOrProspect instanceof Contact) {
  386.             $queryBuilder
  387.                 ->andWhere('cp.contact = :contact')
  388.                 ->setParameter('contact'$contactOrProspect);
  389.         } else {
  390.             $queryBuilder
  391.                 ->andWhere('cp.prospect = :prospect')
  392.                 ->setParameter('prospect'$contactOrProspect);
  393.         }
  394.         return $queryBuilder
  395.             ->getQuery()
  396.             ->getResult();
  397.     }
  398.     public function findByDates(DateTime $startingDateDateTime $endingDate): array
  399.     {
  400.         return $this->createQueryBuilder('pr')
  401.             ->andWhere('pr.appointmentDate >= :startingDate')
  402.             ->andWhere('pr.appointmentDate <= :endingDate')
  403.             ->setParameter('startingDate'$startingDate->format('Y-m-d'))
  404.             ->setParameter('endingDate'$endingDate->format('Y-m-d'))
  405.             ->getQuery()
  406.             ->getResult();
  407.     }
  408.     public function findBySellerAndDates(User $sellerDateTime $startingDateDateTime $endingDate): array
  409.     {
  410.         return $this->createQueryBuilder('pr')
  411.             ->join('pr.assignedUser''s')
  412.             ->where('s = :seller')
  413.             ->andWhere('pr.appointmentDate >= :startingDate')
  414.             ->andWhere('pr.appointmentDate <= :endingDate')
  415.             ->setParameter('seller'$seller)
  416.             ->setParameter('startingDate'$startingDate->format('Y-m-d'))
  417.             ->setParameter('endingDate'$endingDate->format('Y-m-d'))
  418.             ->getQuery()
  419.             ->getResult();
  420.     }
  421.     /**
  422.      * Récupère les demandes de devis d'un contact.
  423.      *
  424.      * @return ProspectRequest[]
  425.      */
  426.     public function findQuoteRequests(Contact $contact): array
  427.     {
  428.         return $this->createQueryBuilder('pr')
  429.             ->innerJoin('pr.type''prt')
  430.             ->innerJoin('pr.contactProspect''cp')
  431.             ->where('cp.contact = :contact')
  432.             ->andWhere('prt.code = :quoteRequest')
  433.             ->setParameters([
  434.                 'contact' => $contact,
  435.                 'quoteRequest' => ParameterCodes::PROSPECT_REQUEST_TYPE_QUOTE_REQUEST,
  436.             ])
  437.             ->getQuery()
  438.             ->getResult()
  439.         ;
  440.     }
  441.     /**
  442.      * @return ProspectRequest[]
  443.      */
  444.     public function findToProcessedBySeller(User $seller, array $originCodes = []): array
  445.     {
  446.         $qb $this->createQueryBuilder('pr');
  447.         $qb $qb
  448.             ->join('pr.assignedUser''s')
  449.             ->join('pr.status''st')
  450.             ->andWhere($qb->expr()->eq('s.id'':sellerId'))
  451.             ->andWhere($qb->expr()->in('st.code'':statusCodes'))
  452.             ->andWhere($qb->expr()->eq('pr.isActive'':isActive'))
  453.             ->setParameter('sellerId'$seller->getId())
  454.             ->setParameter('isActive'true)
  455.             ->setParameter('statusCodes', [
  456.                 ParameterCodes::PROSPECT_REQUEST_STATUS_MUTED,
  457.                 ParameterCodes::PROSPECT_REQUEST_STATUS_ATTRIBUTED_AND_NOT_PROCESSED
  458.             ]);
  459.         if (count($originCodes) > 0) {
  460.             $qb $qb
  461.                 ->join('pr.prospectRequestOrigin''pro')
  462.                 ->andWhere($qb->expr()->in('pro.code'':originCodes'))
  463.                 ->setParameter('originCodes'$originCodes);
  464.         }
  465.         return $qb
  466.             ->orderBy('pr.appointmentDate')
  467.             ->getQuery()
  468.             ->getResult();
  469.     }
  470.     /********************************* home-module *************************************/
  471.     public function countThisDateProspectRequest($type$date, ?bool $assignedUser null): int
  472.     {
  473.         $qb $this->createQueryBuilder('pr')
  474.             ->select('count(pr.id)')
  475.             ->where('pr.createdAt > :date')
  476.             ->andWhere('pr.type = :type');
  477.         if ($assignedUser !== null) {
  478.             $qb $assignedUser === true $qb->andWhere('pr.assignedUser IS NOT NULL') : $qb->andWhere('pr.assignedUser IS NULL');
  479.         }
  480.         return $qb
  481.             ->setParameter('date'$date)
  482.             ->setParameter('type'$type)
  483.             ->getQuery()
  484.             ->getSingleScalarResult();
  485.     }
  486.     public function countBeforeThisDateProspectRequest($type$date, ?bool $assignedUser null): int
  487.     {
  488.         $qb $this->createQueryBuilder('pr')
  489.             ->select('count(pr.id)')
  490.             ->where('pr.createdAt < :date')
  491.             ->andWhere('pr.type = :type')
  492.         ;
  493.         if ($assignedUser !== null) {
  494.             $qb $assignedUser === true $qb->andWhere('pr.assignedUser IS NOT NULL') : $qb->andWhere('pr.assignedUser IS NULL');
  495.         }
  496.         return $qb
  497.             ->setParameter('date'$date)
  498.             ->setParameter('type'$type)
  499.             ->getQuery()
  500.             ->getSingleScalarResult()
  501.         ;
  502.     }
  503.     public function countBetweenThisDateProspectRequest($type$startDate$endDate, ?bool $assignedUser null): int
  504.     {
  505.         $qb $this->createQueryBuilder('pr')
  506.             ->select('count(pr.id)')
  507.             ->where('pr.createdAt > :startDate')
  508.             ->andWhere('pr.createdAt < :endDate')
  509.             ->andWhere('pr.type = :type')
  510.             ->setParameter('startDate'$startDate)
  511.             ->setParameter('endDate'$endDate)
  512.             ->setParameter('type'$type)
  513.         ;
  514.         if ($assignedUser !== null) {
  515.             $qb $assignedUser === true $qb->andWhere('pr.assignedUser IS NOT NULL') : $qb->andWhere('pr.assignedUser IS NULL');
  516.         }
  517.         return $qb
  518.             ->getQuery()
  519.             ->getSingleScalarResult()
  520.         ;
  521.     }
  522.     public function countBetweenThisDateWithOrigin(string $originCode, ?\DateTimeInterface $startDate null, ?\DateTimeInterface $endDate null, ?bool $assignedUser null, ?bool $processToQuote null): int
  523.     {
  524.         $qb $this->createQueryBuilder('pr')
  525.             ->select('count(pr.id)')
  526.             ->join('pr.prospectRequestOrigin''pro')
  527.             ->where('pro.code = :originCode')
  528.             ->setParameter('originCode'$originCode);
  529.         if ($assignedUser !== null) {
  530.             $qb $assignedUser === true $qb->andWhere('pr.assignedUser IS NOT NULL') : $qb->andWhere('pr.assignedUser IS NULL');
  531.         }
  532.         if ($startDate !== null) {
  533.             $qb $qb
  534.                 ->andWhere('pr.createdAt > :startDate')
  535.                 ->setParameter('startDate'$startDate);
  536.         }
  537.         if ($endDate !== null) {
  538.             $qb $qb
  539.                 ->andWhere('pr.createdAt < :endDate')
  540.                 ->setParameter('endDate'$endDate);
  541.         }
  542.         if ($processToQuote !== null) {
  543.             if ($processToQuote === true) {
  544.                 $qb->join('pr.quotes''q');
  545.             }
  546.             else {
  547.                 $qb
  548.                     ->leftJoin('pr.quotes''q')
  549.                     ->andWhere($qb->expr()->isNull('q.id'));
  550.             }
  551.         }
  552.         return $qb
  553.             ->getQuery()
  554.             ->getSingleScalarResult();
  555.     }
  556.     /**
  557.      * @return ProspectRequest[]
  558.      */
  559.     public function findQuoteRequestsMuted(): array
  560.     {
  561.         $qb $this->createQueryBuilder('pr');
  562.         $result $qb
  563.             ->join('pr.prospectRequestOrigin''pro')
  564.             ->join('pr.status''st')
  565.             ->andWhere($qb->expr()->in('pro.code'':codes'))
  566.             ->andWhere($qb->expr()->eq('st.code'':statusCode'))
  567.             ->andWhere($qb->expr()->gte('pr.updatedAt'':nowLess24'))
  568.             ->andWhere($qb->expr()->gte('pr.createdAt'':nowLess7days'))
  569.             ->setParameter('codes', [
  570.                 ParameterCodes::PROSPECT_REQUEST_ORIGIN_WEB,
  571.                 ParameterCodes::PROSPECT_REQUEST_ORIGIN_OTHER
  572.             ])
  573.             ->setParameter('statusCode'ParameterCodes::PROSPECT_REQUEST_STATUS_MUTED)
  574.             ->setParameter('nowLess24', (new DateTime())->modify('-24 hours'))
  575.             ->setParameter('nowLess7days', (new DateTime())->modify('-7 days'))
  576.         ;
  577.         return
  578.             $result
  579.             ->getQuery()
  580.             ->getResult()
  581.         ;
  582.     }
  583.     public function findMutedWithReminderToDo(?User $seller null): array
  584.     {
  585.         $qb $this->createQueryBuilder('pr');
  586.         if ($seller !== null) {
  587.             $qb $qb
  588.                 ->join('pr.assignedUser''u')
  589.                 ->andWhere($qb->expr()->eq('u.id'$seller->getId()));
  590.         }
  591.         return $qb
  592.             ->join('pr.prospectRequestOrigin''pro')
  593.             ->join('pr.status''st')
  594.             ->innerJoin('pr.reminders''r')
  595.             ->andWhere($qb->expr()->eq('st.code'':statusCode'))
  596.             ->andWhere($qb->expr()->lte('r.remindAt'':now'))
  597.             ->andWhere($qb->expr()->eq('r.muted'':muted'))
  598.             ->setParameter('now', new \DateTime())
  599.             ->setParameter('muted'false)
  600.             ->setParameter('statusCode'ParameterCodes::PROSPECT_REQUEST_STATUS_MUTED)
  601.             ->getQuery()
  602.             ->getResult()
  603.         ;
  604.     }
  605.     public function findByOriginAndStateType(string $originCodestring $statusCode): array
  606.     {
  607.         $qb $this->createQueryBuilder('pr');
  608.         return $qb
  609.             ->join('pr.status''st')
  610.             ->join('pr.assignedUser''u')
  611.             ->join('pr.prospectRequestOrigin''pro')
  612.             ->where($qb->expr()->eq('st.code'':statusCode'))
  613.             ->andWhere($qb->expr()->isNotNull('u.id'))
  614.             ->andWhere($qb->expr()->eq('pro.code'':originCode'))
  615.             ->andWhere($qb->expr()->eq('pr.isActive'':isActive'))
  616.             ->setParameter('statusCode'$statusCode)
  617.             ->setParameter('originCode'$originCode)
  618.             ->setParameter('isActive'true)
  619.             ->getQuery()
  620.             ->getResult()
  621.         ;
  622.     }
  623.     /**
  624.      * @param Contact $contact
  625.      * @param QueryBuilder|null $queryBuilder
  626.      * @return QueryBuilder
  627.      */
  628.     private function getContactQuoteRequestsBaseQueryBuilder(Contact $contact, ?QueryBuilder $queryBuilder null): QueryBuilder
  629.     {
  630.         if ($queryBuilder === null) {
  631.             $queryBuilder $this->createQueryBuilder('pr');
  632.         }
  633.         else {
  634.             $queryBuilder $queryBuilder->from(ProspectRequest::class, 'pr');
  635.         }
  636.         return $queryBuilder
  637.             ->select('pr''pro')
  638.             ->join('pr.prospectRequestOrigin''pro')
  639.             ->join('pr.type''pt')
  640.             ->join('pr.contactProspect''cp')
  641.             ->join('cp.contact''c')
  642.             ->leftJoin('pr.assignedUser''s')
  643.             ->leftJoin('pr.cruiseHistory''cr')
  644.             ->leftJoin('pr.cabinCategoryHistory''cch')
  645.             ->andWhere($queryBuilder->expr()->in('pt.code'':codes'))
  646.             ->andWhere($queryBuilder->expr()->eq('c.id'$contact->getId()))
  647.             ->andWhere($queryBuilder->expr()->eq('pr.isActive'':isActive'))
  648.             ->setParameter('codes', [
  649.                 ParameterCodes::PROSPECT_REQUEST_TYPE_QUOTE_REQUEST
  650.             ])
  651.             ->setParameter('isActive'true);
  652.     }
  653.     /**
  654.      * @param Contact $contact
  655.      * @param QueryBuilder|null $queryBuilder
  656.      * @return QueryBuilder
  657.      */
  658.     public function getContactQuoteRequestsInProgressQueryBuilder(Contact $contact, ?QueryBuilder $queryBuilder null): QueryBuilder
  659.     {
  660.         $queryBuilder $this->getContactQuoteRequestsBaseQueryBuilder($contact$queryBuilder);
  661.         return $queryBuilder->andWhere($queryBuilder->expr()->eq('pr.isQuoteSent'0));
  662.     }
  663.     /**
  664.      * @param Contact $contact
  665.      * @param QueryBuilder|null $queryBuilder
  666.      * @return QueryBuilder
  667.      */
  668.     public function getContactPastQuoteRequestsQueryBuilder(Contact $contact, ?QueryBuilder $queryBuilder null): QueryBuilder
  669.     {
  670.         $queryBuilder $this->getContactQuoteRequestsBaseQueryBuilder($contact$queryBuilder);
  671.         return $queryBuilder->andWhere($queryBuilder->expr()->eq('pr.isQuoteSent'1));
  672.     }
  673.     /**
  674.      * Get the list of current quote requests for a contact
  675.      *
  676.      * @param Contact $contact
  677.      * @return array
  678.      */
  679.     public function getContactQuoteRequestsInProgress(Contact $contact): array
  680.     {
  681.         return $this->getContactQuoteRequestsInProgressQueryBuilder($contact)
  682.             ->getQuery()
  683.             ->getResult();
  684.     }
  685.     /**
  686.      * Get the list of past quote requests for a contact
  687.      *
  688.      * @param Contact $contact
  689.      * @return array
  690.      */
  691.     public function getContactPastQuoteRequests(Contact $contact): array
  692.     {
  693.         return $this->getContactPastQuoteRequestsQueryBuilder($contact)
  694.             ->getQuery()
  695.             ->getResult();
  696.     }
  697.     /**
  698.      * Get the list of all quote requests for a contact
  699.      *
  700.      * @param Contact $contact
  701.      * @return array
  702.      */
  703.     public function getContactAllQuoteRequests(Contact $contact): array
  704.     {
  705.         return $this->getContactQuoteRequestsBaseQueryBuilder($contact)
  706.             ->getQuery()
  707.             ->getResult();
  708.     }
  709.     /**
  710.      * @return array|ProspectRequest[]
  711.      */
  712.     public function findProspectRequestWithAnomalies(): array
  713.     {
  714.         $qb $this->createQueryBuilder('pr');
  715.         return $qb
  716.             ->join('pr.status''prst')
  717.             ->leftJoin('pr.statusReason''prr')
  718.             ->where($qb->expr()->eq('prst.code'':statusCode'))
  719.             ->andWhere($qb->expr()->isNull('prr.id'))
  720.             ->andWhere($qb->expr()->isNotNull('pr.statusChangeLastDate'))
  721.             ->andWhere($qb->expr()->lt('pr.statusChangeLastDate'':statusChangeLastDate'))
  722.             ->setParameter('statusCode'ParameterCodes::PROSPECT_REQUEST_STATUS_WITH_DIALOG_WITHOUT_QUOTE)
  723.             ->setParameter('statusChangeLastDate', (new DateTime())->modify('-7 days'))
  724.             ->getQuery()
  725.             ->getResult();
  726.     }
  727.     /**
  728.      * @return array|ProspectRequest[]
  729.      */
  730.     public function findProspectRequestFromStatus(string $statusCode): array
  731.     {
  732.         $qb $this->createQueryBuilder('pr');
  733.         return $qb
  734.             ->join('pr.status''prst')
  735.             ->where($qb->expr()->eq('prst.code'':statusCode'))
  736.             ->setParameter('statusCode'$statusCode)
  737.             ->getQuery()
  738.             ->getResult();
  739.     }
  740.     /**
  741.      * @return array|ProspectRequest[]
  742.      */
  743.     public function findActiveProspectRequestsFromUser(User $user): array
  744.     {
  745.         $qb $this->createQueryBuilder('pr');
  746.         return $qb
  747.             ->join('pr.assignedUser''au')
  748.             ->join('pr.status''prst')
  749.             ->where($qb->expr()->eq('au.id'$user->getId()))
  750.             ->andWhere($qb->expr()->eq('prst.code'':statusCode'))
  751.             ->setParameter('statusCode'ParameterCodes::PROSPECT_REQUEST_STATUS_ATTRIBUTED_AND_NOT_PROCESSED)
  752.             ->getQuery()
  753.             ->getResult();
  754.     }
  755. }