<?php
namespace App\Repository\User;
use App\Entity\ParameterCodes;
use App\Entity\User\User;
use App\Voter\__Accounting\AccountingTurnoverVoter;
use App\Voter\BookingVoter;
use App\Voter\QuoteVoter;
use App\Voter\__Accounting\AccountingSellingVoter;
use Crea\HRBundle\Helper\PlanningHelper;
use Crea\SecurityBundle\Helper\AccessHelper;
use Crea\SecurityBundle\Model\Access;
use Crea\SecurityBundle\Repository\UserRepository as BaseUserRepository;
use DateTime;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Security;
use Throwable;
/**
* @method User|null find($id, $lockMode = null, $lockVersion = null)
* @method User|null findOneBy(array $criteria, array $orderBy = null)
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends BaseUserRepository
{
public const CRM_USER_GROUPS = [
['label' => 'Administrateur', 'code' => 'Administrateur', 'crmId' => 1],
['label' => 'Commercial', 'code' => 'Commercial', 'crmId' => 2],
['label' => 'Marketing', 'code' => 'Marketing', 'crmId' => 3],
['label' => 'Stagiaire', 'code' => 'Stagiaire', 'crmId' => 4],
['label' => 'Comptabilité', 'code' => 'Comptabilite', 'crmId' => 5],
['label' => 'Direction', 'code' => 'Direction', 'crmId' => 6],
['label' => 'Back-Office', 'code' => 'Back-Office', 'crmId' => 7],
['label' => 'Vendeur', 'code' => 'Vendeur', 'crmId' => 8],
['label' => 'Manager plateau', 'code' => 'Manager-plateau', 'crmId' => 9],
['label' => 'Partenariats', 'code' => 'Partenariats', 'crmId' => 10],
['label' => 'Technique', 'code' => 'Technique', 'crmId' => 11],
['label' => 'Anciens utilisateurs', 'code' => 'Anciens-utilisateurs', 'crmId' => 12],
];
public const DEFAULT_USER_GROUP_CODE = 'Anciens-utilisateurs';
public const SELLER_USER_GROUP_CODE = 'Vendeur';
public const BACK_OFFICE_USER_GROUP_CODE = 'Back-Office';
public const ACCOUNTING_USER_GROUP_CODE = 'Comptabilite';
public const MANAGER_USER_GROUP_CODE = 'Manager-plateau';
public const MARKETING_USER_GROUP_CODE = 'Marketing';
public const FULLWEB_USER_LOGIN = 'croisiland';
protected Security $security;
protected AccessHelper $accessHelper;
protected PlanningHelper $planningHelper;
public function __construct(ManagerRegistry $registry,
Security $security,
AccessHelper $accessHelper,
PlanningHelper $planningHelper)
{
parent::__construct($registry, User::class);
$this->security = $security;
$this->accessHelper = $accessHelper;
$this->planningHelper = $planningHelper;
}
public function loadUserByUsername(string $usernameOrEmail): ?User
{
try {
return $this->createQueryBuilder('u')
->where('u.login = :usernameOrEmail')
->orWhere('u.email = :usernameOrEmail')
->setParameter('usernameOrEmail', $usernameOrEmail)
->getQuery()
->getOneOrNullResult();
} catch (NonUniqueResultException $e) {
return null;
}
}
public function getAllOrderedByNameQueryBuilder(): QueryBuilder
{
return $this->createQueryBuilder('u')
->addOrderBy('u.firstName', 'ASC')
->addOrderBy('u.lastName', 'ASC');
}
/**
* @throws NonUniqueResultException
*/
public function findOneByAccountToken(string $token): ?User
{
return $this->createQueryBuilder('u')
->where('u.accountToken = :token')
->setParameter('token', $token)
->getQuery()
->getOneOrNullResult();
}
/**
* @throws NonUniqueResultException
*/
public function findFullwebUser(): ?User
{
return $this->createQueryBuilder('u')
->where('u.login = :login')
->setParameter('login', self::FULLWEB_USER_LOGIN)
->getQuery()
->getOneOrNullResult();
}
/**
* @return User[]
*/
public function findIn(array $ids): array
{
$qb = $this->createQueryBuilder('u');
return $qb
->where($qb->expr()->in('u.id', ':ids'))
->setParameter('ids', $ids)
->getQuery()
->getResult()
;
}
/*********************************** By Users Group ***************************************************************/
public function getByUserGroupCodeQB(string $userGroupCode, ?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
$qb = $this->createQueryBuilder('u');
$qb->leftjoin('u.userGroups', 'ug')
->andWhere($qb->expr()->eq('ug.code', ':userGroupCode'))
->setParameter('userGroupCode', $userGroupCode);
if ($enabled !== null) {
$qb->andWhere($qb->expr()->eq('u.enabled', ':enabled'))
->setParameter('enabled', $enabled);
}
$qb->groupBy('u.id');
if ($orderedByName === true) {
$qb->addOrderBy('u.firstName', 'ASC')
->addOrderBy('u.lastName', 'ASC');
}
return $qb;
}
public function getByUserGroupsCodeQB(array $userGroupsCode, ?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
$qb = $this->createQueryBuilder('u');
$qb->leftjoin('u.userGroups', 'ug')
->andWhere($qb->expr()->in('ug.code', ':userGroupsCode'))
->setParameter('userGroupsCode', $userGroupsCode);
if ($enabled !== null) {
$qb->andWhere($qb->expr()->eq('u.enabled', ':enabled'))
->setParameter('enabled', $enabled);
}
$qb->groupBy('u.id');
if ($orderedByName === true) {
$qb->addOrderBy('u.firstName', 'ASC')
->addOrderBy('u.lastName', 'ASC');
}
return $qb;
}
/**
* @return User[]
*/
public function findGroupUsers(string $userGroupCode, ?bool $enabled = true, ?bool $orderedByName = true): array
{
return $this->getByUserGroupCodeQB($userGroupCode, $enabled, $orderedByName)->getQuery()->getResult();
}
/*********************************** ADV Users Group **************************************************************/
public function getAdvUsersQueryBuilder(?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
return $this->getByUserGroupCodeQB(self::BACK_OFFICE_USER_GROUP_CODE, $enabled, $orderedByName);
}
/**
* @return User[]
*/
public function findAdvUsers(?bool $enabled = true, ?bool $orderedByName = true): array
{
return $this->getAdvUsersQueryBuilder($enabled, $orderedByName)->getQuery()->getResult();
}
public function getAdvRequestsCount(): array
{
return $this->getSellerUsersQueryBuilder()
->select('u.id as sellerId')
->addSelect('count(DISTINCT ar) as count')
->leftjoin('u.advRequests', 'ar')
->getQuery()
->getResult();
}
/*********************************** Seller Users Group ***********************************************************/
public function getSellerUsersQueryBuilder(?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
return $this->getByUserGroupCodeQB(self::SELLER_USER_GROUP_CODE, $enabled, $orderedByName);
}
public function getSellerUsersAvailableQueryBuilder(bool $available, DateTime $date, ?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
$qb = $this->getSellerUsersQueryBuilder($enabled, $orderedByName);
$unavailableUsers = $this->planningHelper->getNotAvailableUsersFromGroupAndDateQb(self::SELLER_USER_GROUP_CODE, $date)->getQuery()->getResult();
if ($available) {
if (count($unavailableUsers) > 0) {
$qb->andWhere($qb->expr()->notIn('u', ':userList'))
->setParameter('userList', $unavailableUsers);
}
}
else {
$qb->andWhere($qb->expr()->in('u', ':userList'))
->setParameter('userList', $unavailableUsers);
}
return $qb;
}
/********************************** Marketing Users Group *********************************************************/
public function getMarketingUsersQueryBuilder(?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
return $this->getByUserGroupCodeQB(self::MARKETING_USER_GROUP_CODE, $enabled, $orderedByName);
}
public function getMarketingUsersAvailableQueryBuilder(bool $available, DateTime $date, ?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
$qb = $this->getMarketingUsersQueryBuilder($enabled, $orderedByName);
$unavailableUsers = $this->planningHelper->getNotAvailableUsersFromGroupAndDateQb(self::MARKETING_USER_GROUP_CODE, $date)->getQuery()->getResult();
if ($available) {
if (count($unavailableUsers) > 0) {
$qb->andWhere($qb->expr()->notIn('u', ':userList'))
->setParameter('userList', $unavailableUsers);
}
}
else {
$qb->andWhere($qb->expr()->in('u', ':userList'))
->setParameter('userList', $unavailableUsers);
}
return $qb;
}
private function completeQueryBuilderForUserWithoutAccess(QueryBuilder $qb, array $rights): QueryBuilder
{
if (!$this->accessHelper->hasAccess(new Access($rights))) {
/** @var User $user */
$user = $this->security->getUser();
$qb = $qb->andWhere($qb->expr()->eq('u.id', $user->getId()));
}
return $qb;
}
public function getSellerUsersForQuoteListQueryBuilder(): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getSellerUsersQueryBuilder(),
[QuoteVoter::SHOW_ALL_SELLERS]
);
}
public function getSellerUsersForQuoteOptionInProgressQueryBuilder(): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getSellerUsersQueryBuilder(),
[QuoteVoter::OPTION_IN_PROGRESS_SHOW_ALL_SELLERS]
);
}
public function getSellerUsersForBookingListQueryBuilder(): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getSellerUsersQueryBuilder(),
[BookingVoter::SHOW_ALL_SELLERS]
);
}
public function getSellerUsersForSellerRecapQueryBuilder(): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getSellerUsersQueryBuilder(),
[AccountingSellingVoter::SELLER_SALE_SHOW_ALL_SELLERS]
);
}
public function getSellerUsersForPartnerRecapQueryBuilder(): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getSellerUsersQueryBuilder(),
[AccountingSellingVoter::PARTNER_SALE_SHOW_ALL_SELLERS]
);
}
public function getSellerUsersForCompanyRecapQueryBuilder(): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getSellerUsersQueryBuilder(),
[AccountingSellingVoter::COMPANY_SALE_SHOW_ALL_SELLERS]
);
}
public function getSellerUsersForCabinTypeRecapQueryBuilder(): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getSellerUsersQueryBuilder(),
[AccountingSellingVoter::CABIN_SALE_SHOW_ALL_SELLERS]
);
}
public function getSellerUsersForTurnoverRecapBySellerQueryBuilder(): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getSellerUsersQueryBuilder(),
[AccountingTurnoverVoter::SELLER_SHOW_ALL_SELLERS]
);
}
/**
* @return User[]
*/
public function findSellerUsers(?bool $enabled = true, ?bool $orderedByName = true): array
{
return $this->getSellerUsersQueryBuilder($enabled, $orderedByName)->getQuery()->getResult();
}
/**
* @return User[]
*/
public function findMarketingUsers(?bool $enabled = true, ?bool $orderedByName = true): array
{
return $this->getMarketingUsersQueryBuilder($enabled, $orderedByName)->getQuery()->getResult();
}
public function getSellersRequestsCount(): array
{
return $this->getSellerUsersQueryBuilder()
->select('u.id as sellerId')
->addSelect('count(DISTINCT pr) as count')
->leftjoin('u.prospectRequests', 'pr', Join::WITH, 'pr.stateType = :attributedStateTypeId')
->leftJoin('pr.status', 'prs')
->where('prs.code', ':attributedStateCode')
->setParameter('attributedStateCode', ParameterCOdes::PROSPECT_REQUEST_STATUS_ATTRIBUTED_AND_NOT_PROCESSED)
->getQuery()
->getResult();
}
/**
* Retourne le nombre des réservations des vendeurs sur une période donnée.
*
* @return User[]
*/
public function getSellersCabinCount(DateTime $startingDate, DateTime $endingDate): array
{
$qb = $this->getSellerUsersQueryBuilder(null)
->select('u.id as sellerId')
->addSelect('count(DISTINCT qrg) as count')
->join('u.bookings', 'b')
->andWhere('b.assignedAt >= :startingDate')
->setParameter('startingDate', $startingDate)
->andWhere('b.assignedAt <= :endingDate')
->setParameter('endingDate', $endingDate);
return $qb->getQuery()->getResult();
}
/**
* @return User[]
*/
public function getSellersBookingCount(?DateTime $startingDate, ?DateTime $endingDate, ?string $status = null): array
{
$queryBuilder = $this->createQueryBuilder('u')
->leftjoin('u.quotes', 'q')
->select('u.id as sellerId')
->addSelect('count(DISTINCT booking) as count')
->join('q.booking', 'booking');
if (null !== $startingDate) {
$queryBuilder
->andWhere('booking.assignedAt >= :startingDate')
->setParameter('startingDate', $startingDate);
}
if (null !== $endingDate) {
$queryBuilder
->andWhere('booking.assignedAt <= :endingDate')
->setParameter('endingDate', $endingDate);
}
if (null !== $status) {
$queryBuilder
->andWhere('booking.status = :status')
->setParameter('status', $status);
}
return $queryBuilder
->groupBy('u.id')
->addGroupBy('booking.id')
->getQuery()
->getResult()
;
}
/*********************************** Accounting Users Group *******************************************************/
public function getAccountingUsersQueryBuilder(?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
return $this->getByUserGroupCodeQB(self::ACCOUNTING_USER_GROUP_CODE, $enabled, $orderedByName);
}
/**
* @return User[]
*/
public function findAccountingUsers(?bool $enabled = true, ?bool $orderedByName = true): array
{
return $this->getAccountingUsersQueryBuilder($enabled, $orderedByName)->getQuery()->getResult();
}
/*********************************** Manager Users Group **********************************************************/
public function getManagerUsersQueryBuilder(?bool $enabled = true, ?bool $orderedByName = true): QueryBuilder
{
return $this->getByUserGroupCodeQB(self::MANAGER_USER_GROUP_CODE, $enabled, $orderedByName);
}
/**
* @return User[]
*/
public function findManagerUsers(?bool $enabled = true, ?bool $orderedByName = true): array
{
return $this->getManagerUsersQueryBuilder($enabled, $orderedByName)->getQuery()->getResult();
}
public function findAdvManager(?bool $enabled = true, ?bool $orderedByName = true): ?User
{
try {
return $this->getManagerUsersQueryBuilder($enabled, $orderedByName)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
} catch (Throwable $exception) {
return null;
}
}
/*********************************** Schedule *********************************************************************/
/**
* Retourne la liste des utilisateurs du groupe passé en paramètre avec leurs informations liées au planning.
*
* @return User[]
*/
public function getScheduleEvents(string $userGroupCode, DateTime $startingDate, DateTime $endingDate): array
{
return $this->getByUserGroupCodeQB($userGroupCode)
->select('u, se')
->leftJoin('u.scheduleEvents', 'se', 'WITH', 'se.date >= :startingDate AND se.date <= :endingDate')
->setParameter('startingDate', $startingDate->format('Y-m-d'))
->setParameter('endingDate', $endingDate->format('Y-m-d'))
->addOrderBy('se.date', 'ASC')
->addOrderBy('se.startingTime', 'ASC')
->getQuery()
->getResult();
}
/**
* Retourne la liste des utilisateurs du groupe passé en paramètre avec leurs commentaires planning.
*
* @return User[]
*/
public function getScheduleComments(string $userGroupCode, DateTime $startingDate, DateTime $endingDate): array
{
return $this->getByUserGroupCodeQB($userGroupCode)
->select('u, sc')
->leftJoin('u.scheduleComments', 'sc', 'WITH', 'sc.date >= :startingDate AND sc.date <= :endingDate')
->setParameter('startingDate', $startingDate->format('Y-m-d'))
->setParameter('endingDate', $endingDate->format('Y-m-d'))
->getQuery()
->getResult();
}
/**
* Retourne la liste des utilisateurs du groupe passé en paramètre avec leurs congés.
*
* @return User[]
*/
public function getScheduleLeaves(string $userGroupCode, DateTime $startingDate, DateTime $endingDate): array
{
return $this->getByUserGroupCodeQB($userGroupCode)
->select('u, l')
->leftJoin('u.leaves', 'l', 'WITH', 'l.endingDate >= :startingDate AND l.startingDate <= :endingDate')
->setParameter('startingDate', $startingDate->format('Y-m-d'))
->setParameter('endingDate', $endingDate->format('Y-m-d'))
->getQuery()
->getResult();
}
/**
* Retourne la liste des utilisateurs du groupe passé en paramètre avec leurs informations liées au planning pour les PDF.
*
* @return User[]
*/
public function getScheduleDataForPdf(string $userGroupCode, DateTime $startingDate, DateTime $endingDate): array
{
return $this->getByUserGroupCodeQB($userGroupCode)
->select('u, se, l')
->leftJoin('u.scheduleEvents', 'se', 'WITH', 'se.date >= :startingDate AND se.date <= :endingDate')
->leftJoin('u.leaves', 'l', 'WITH', 'l.endingDate >= :startingDate AND l.startingDate <= :endingDate')
->setParameter('startingDate', $startingDate->format('Y-m-d'))
->setParameter('endingDate', $endingDate->format('Y-m-d'))
->addOrderBy('u.firstName', 'ASC')
->addOrderBy('se.date', 'ASC')
->addOrderBy('se.startingTime', 'ASC')
->getQuery()
->getResult();
}
/**
* Retourne la liste des utilisateurs du groupe passé en paramètre avec leurs demandes à traiter.
*
* @return User[]
*/
public function getProspectRequestsForSchedule(string $userGroupCode, DateTime $startingDate, DateTime $endingDate): array
{
return $this->getByUserGroupCodeQB($userGroupCode)
->select('u, pr')
->leftJoin('u.prospectRequests', 'pr', 'WITH', 'pr.appointmentDate >= :startingDate AND pr.appointmentDate <= :endingDate')
->setParameter('startingDate', $startingDate->format('Y-m-d'))
->setParameter('endingDate', $endingDate->format('Y-m-d'))
->addOrderBy('pr.appointmentDate', 'ASC')
->addOrderBy('pr.appointmentHours', 'ASC')
->getQuery()
->getResult();
}
/**
* Retourne la liste des utilisateurs du groupe passé en paramètre avec leurs demandes ADV à traiter.
*
* @return User[]
*/
public function getAdvRequestsForSchedule(string $userGroupCode, DateTime $startingDate, DateTime $endingDate): array
{
return $this->getByUserGroupCodeQB($userGroupCode)
->select('u, ar')
->leftJoin('u.advRequests', 'ar', 'WITH', 'ar.appointmentDate >= :startingDate AND ar.appointmentDate <= :endingDate')
->setParameter('startingDate', $startingDate->format('Y-m-d'))
->setParameter('endingDate', $endingDate->format('Y-m-d'))
->addOrderBy('ar.appointmentDate', 'ASC')
->addOrderBy('ar.appointmentHours', 'ASC')
->getQuery()
->getResult();
}
/*********************************** Recap ************************************************************************/
/**
* @param QueryBuilder $bookingRecapFiltersQueryBuilder Voir fonction getRecapBaseQueryBuilderForFilters du BookingRepository
*/
public function getRecapBaseQueryBuilder(QueryBuilder $bookingRecapFiltersQueryBuilder): QueryBuilder
{
return $this->createQueryBuilder('u')
->select('CONCAT(u.firstName, \' \', u.lastName) as seller')
->innerJoin('u.sellerBookings', 'b')
->where('b.id IN ('.$bookingRecapFiltersQueryBuilder->getQuery()->getDQL().')')
->andWhere('b.seller IS NOT NULL')
->groupBy('u.id')
->addOrderBy('u.firstName', 'ASC')
->addOrderBy('u.lastName', 'ASC');
}
public function getTurnoverRecapBySellerQueryBuilder(QueryBuilder $bookingRecapFiltersQueryBuilder): QueryBuilder
{
return $this->completeQueryBuilderForUserWithoutAccess(
$this->getRecapBaseQueryBuilder($bookingRecapFiltersQueryBuilder),
[AccountingTurnoverVoter::SELLER_SHOW_ALL_SELLERS]
);
}
/*********************************** Grid / Notifications *********************************************************/
public function getAppUsersQueryBuilder(?bool $enabled = true): QueryBuilder
{
$queryBuilder = $this->createQueryBuilder('u');
if (null !== $enabled) {
$queryBuilder
->andWhere('u.enabled = :enabled')
->setParameter('enabled', $enabled);
}
return $queryBuilder
->addOrderBy('u.firstName', 'ASC')
->addOrderBy('u.lastName', 'ASC');
}
public function getSellerFilterGridQueryBuilder(): QueryBuilder
{
return $this->getByUserGroupCodeQB(self::SELLER_USER_GROUP_CODE);
}
}