<?php
namespace App\Repository\AssistantMaternel;
use App\Entity\AssistantMaternel\Agrement;
use App\Entity\Commun\Utilisateur;
use App\Entity\GDA\PlanningDispo;
use App\Entity\GDA\Accueil;
use App\Entity\OffreAccueil\DispoPublicAssmat;
use App\Entity\Referentiel\BureauDistributeur;
use App\Entity\Referentiel\EnumLieuAccueil;
use App\Utils\StringUtils;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
/**
* AssistantMaternelRepository
* Repository des Assistants Maternels via ORM Doctrine
*/
class AssistantMaternelRepository extends \Doctrine\ORM\EntityRepository
{
//TODO
protected $logger = null;
function setLogger($logger)
{
$this->logger = $logger;
}
/**
* Rechercher des assmats selon des critères cumulatifs
* @param string $nom commence par
* @param string $prenom commence par
* @param Commune? $commune
* @param Utilisateur $user
* @param bool $inclureArchive indique si les assmats archivées doivent faire partie des résultats
* @param bool $inclureCreche indique si les assmats en creche doivent faire partie des résultats
* @param array $paramsDatatable
* @return App\Repository\AssistantMaternel
* La liste des assmats renvoyée est triée par nom puis prénom
*/
public function listePartenaire(string $nom, string $prenom, $commune, $user, bool $inclureArchive, bool $inclureCreche, $paramsDatatable)
{
/* initialise la requête avec un select 'ass' from AssistantMaternel */
$qb = $this->createQueryBuilder('ass')
// On prend aussi en compte la MAM pour l'utiliser dans les jointures
->leftJoin('ass.mam', 'mam')
->addSelect('mam')
->leftJoin('mam.preferences_publication', 'pref_mam')
->addSelect('pref_mam')
->leftJoin('mam.presentation_mam', 'pres_mam')
->addSelect('pres_mam')
// Fix perf lazy loading onetoone
->leftJoin('ass.preferences_publication', 'pref')
->addSelect('pref')
->leftJoin('ass.presentation_assmat', 'pres')
->addSelect('pres')
// Pré-chargement
->leftJoin('ass.commune', 'c')
->addSelect('c')
// Pour le calcul de la possibilité de déclaration d'accueil
->leftJoin('ass.agrements', 'agr')
->addSelect('agr')
;
if (trim($nom) !== '') {
$nom = StringUtils::str_sanitize($nom);
$qb->andWhere('LOWER(UNACCENT(ass.nom_famille)) LIKE LOWER(UNACCENT(:nom))')
->setParameter('nom', trim($nom) . '%');
}
if (trim($prenom) !== '') {
$prenom = StringUtils::str_sanitize($prenom);
$qb->andWhere('LOWER(UNACCENT(ass.prenom)) LIKE LOWER(UNACCENT(:prenom))')
->setParameter('prenom', '%' . trim($prenom) . '%');
}
if ($commune) {
//restreint aux assmats avec un agrément existant selon le lieu fourni (pas de contrôle sur la date de fin)
$qb->andWhere('((ass.commune = :commune AND ass.date_debut_agrement_domicile is not null) OR ( mam.commune = :commune AND ass.date_debut_agrement_mam is not null))');
$qb->setParameter('commune', $commune);
} else if ($user->getCommunes() && count($user->getCommunes()) > 0) {
//limiter aux communes de l'utlisateur si restreint
$listeCommunes = $user->getCommunes();
//restreint aux assmats avec un agrément existant selon le lieu fourni (pas de contrôle sur la date de fin)
$qb->andWhere('((ass.commune IN (:commune) AND ass.date_debut_agrement_domicile is not null) OR ( mam.commune IN (:commune) AND ass.date_debut_agrement_mam is not null))');
$qb->setParameter('commune', $listeCommunes);
}
//si l'utilisateur n'a pas de commune associée => il peut voir tout le département
if (!$inclureArchive) {
$qb->andWhere(' (ass.archive_domicile = false OR ass.archive_mam = false )'); //il faut eu moins avoir un des 2 lieux pas archive pour apparaitre
$qb->andWhere(' (ass.cta_dom is NULL OR ass.cta_dom = false )');
$qb->andWhere(' (ass.cta_mam is NULL OR ass.cta_mam = false )');
$qb->andWhere(' (ass.suspension_dom is NULL OR ass.suspension_dom = false )');
$qb->andWhere(' (ass.suspension_mam is NULL OR ass.suspension_mam = false )');
}
if (!$inclureCreche) {
$qb->andWhere('(ass.creche is NULL OR ass.creche = false)');
}
// on ne veut que les assmats non-opposées (cf leguay 13/01/2022)
// et que les assmats ayant fait la formation 1 (cf leguay 13/11/2022 EVO 26)
$qb->andWhere('ass.oppose = false');
$qb->andWhere('(ass.formation1_effectuee is NULL OR ass.formation1_effectuee = true)');
$qb->andWhere('(ass.supprime is null or ass.supprime = false)');
// TODO : on exclut les assmats sans aucune place agree
// $qb->groupBy('ass.id')->having('SUM(agr.nombre_places) > 0');
// pseudo-colonne archive agrégée des 2 champs archive par lieu d'agrément
$qb->addSelect('CASE WHEN ass.archive_domicile = true AND ass.archive_mam = true THEN true ELSE false END AS HIDDEN hid_archive ');
\App\Utils\DatatablesUtils::ajouterCritereTri($qb, $paramsDatatable, [
'0' => ['ass.nom_famille'],
'1' => ['ass.prenom'],
'2' => ['ass.adresse'], // adresse - NON triable
'3' => ['ass.code_postal'],
'4' => ['c.libelle'], //commune
'5' => ['ass.tel_fixe'], //telephone fixe - NON triable
'6' => ['ass.tel_portable'], //telephone port - NON triable
'7' => ['ass.email'], //mail - NON triable
'8' => ['hid_archive'],
//'9' => ['hid_nb_places'], // non triable
]);
$qb->setFirstResult($paramsDatatable[\App\Utils\DatatablesUtils::START]); // à partir du resultat n° offset
if ($paramsDatatable[\App\Utils\DatatablesUtils::LENGTH] <> -1) {
$qb->setMaxResults($paramsDatatable[\App\Utils\DatatablesUtils::LENGTH]); // nb de resultats de la page
}
$query = $qb->getQuery();
$paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($query);
return $paginator;
}
/**
* Rechercher des assmats selon des critères cumulatifs
* @param int? $idFonctionnel
* @param string $nom commence par
* @param string $prenom comemnce par
* @param Canton? $canton
* @param int? $idSecteurPmi
* @param Commune? $commune
* @param BureauDistributeur? $bureauDistributeur
* @param int? $idLieu
* @param bool $formation2 formation2 effectuée ou pas
* @param bool $premierAccueil c'est le 1er accueil de l'assmat ou pas
* @param bool $offreAccueil offre d'accueil saisie ou pas
* @param bool $inclureArchive indique si les assmats archivées doivent faire partie des résultats
* @param bool $inclurePuericultrice indique si les assmats surchargées par la puer doivent faire partie des résultats
* @param utilisateur $puericultrice utilisateur connecté en train de réaliser une recherche
* @param bool $inclureSupprime indique si les assmats supprimées doivent faire partie des résultats
* @param TrancheAge $trancheAge tranche d'âge où l'assmat éligible doit avoir au moins une place agréée
* @param array $paramsDatatable
* @param bool $inclureDispoGrandPublic indique si on doit remonter le nombre de places disponibles (si module grand public présent)
* @return App\Repository\AssistantMaternel
* La liste des assmats renvoyée est triée par nom puis prénom
*/
public function rechercher(string $idFonctionnel, string $nom, string $prenom, $canton, int $idSecteurPmi, $commune, $bureauDistributeur,
int $idLieu, bool $formation2 = null, bool $premierAccueil = null, bool $offreAccueil = null, bool $inclureArchive, bool $inclurePuericultrice, \App\Entity\Commun\Utilisateur $puericultrice,
bool $inclureSupprime, $trancheAge, $paramsDatatable, bool $inclureDispoGrandPublic, bool $listes = false)
{
/* initialise la requête avec un select 'ass' from AssistantMaternel */
$qb = $this->createQueryBuilder('ass')
// On prend aussi en compte la MAM pour l'utiliser dans les jointures
->leftJoin('ass.mam', 'mam')
->addSelect('mam')
->leftJoin('mam.preferences_publication', 'pref_mam')
->addSelect('pref_mam')
->leftJoin('mam.presentation_mam', 'pres_mam')
->addSelect('pres_mam')
// Fix perf lazy loading onetoone
->leftJoin('ass.preferences_publication', 'pref')
->addSelect('pref')
->leftJoin('ass.presentation_assmat', 'pres')
->addSelect('pres')
// Pré-chargement
->leftJoin('ass.commune', 'c')
->addSelect('c')
// Pour le calcul de la possibilité de déclaration d'accueil
->leftJoin('ass.agrements', 'agr')
->addSelect('agr')
// Pour le calcul des badges Nuit et Atypique
->leftJoin('ass.accueils', 'acc')
->addSelect('acc')
//TODO : regarder pourquoi on fait la jointure sur log??
->leftJoin('acc.log_accueil', 'log')
->addSelect('log');
if ($listes) {
$qb->leftJoin('ass.secteur_pmi', 's');
}
// On n'utilise pas la fonction empty() car renvoie true avec la chaine de caractères "0"
if (trim($idFonctionnel) !== '') {
$qb->andWhere('ass.id_fonctionnel = :idFonctionnel')
->setParameter('idFonctionnel', trim($idFonctionnel));
}
if (trim($nom) !== '') {
$nom = StringUtils::str_sanitize($nom);
$qb->andWhere('LOWER(UNACCENT(ass.nom_famille)) LIKE LOWER(UNACCENT(:nom))')
->setParameter('nom', trim($nom) . '%');
}
if (trim($prenom) !== '') {
$prenom = StringUtils::str_sanitize($prenom);
$qb->andWhere('LOWER(UNACCENT(ass.prenom)) LIKE LOWER(UNACCENT(:prenom))')
->setParameter('prenom', '%' . trim($prenom) . '%');
}
if ($canton) {
$qb->innerJoin('ass.canton', 'can', Join::WITH, '(ass.date_debut_agrement_domicile is not null and ass.canton.id = :canton)'
. 'or'
. '(ass.date_debut_agrement_mam is not null and mam.canton.id = :canton)'
)
->setParameter('canton', $canton);
}
if ($idSecteurPmi != 0) {
if ($inclurePuericultrice && $puericultrice != null) {
//on veut à la fois les assmats du secteur et celles de la puer connectée
$qb = $qb->innerJoin('ass.secteur_pmi', 'sec')
->andWhere('sec.id = :secteur OR ass.puericultrice = :puericultrice')
->setParameter('secteur', $idSecteurPmi)
->setParameter('puericultrice', $puericultrice);
} else {
//seulement secteur
$qb = $qb->innerJoin('ass.secteur_pmi', 'sec')
->andWhere('sec.id = :secteur')
->setParameter('secteur', $idSecteurPmi);
}
}
if ($commune) {
// Cas 1 : lieu d'exercice à domicile uniquement
if ($idLieu & EnumLieuAccueil::DOMICILE && !($idLieu & EnumLieuAccueil::MAM)) {
$qb->andWhere('ass.commune = :commune');
}
// Cas 2 : lieu d'exercice en MAM uniquement
else if ($idLieu & EnumLieuAccueil::MAM && !($idLieu & EnumLieuAccueil::DOMICILE)) {
$qb->andWhere('mam.commune = :commune');
}
// Cas 3 : lieu d'exercice indifférent (ou double agrément)
else {
$qb->andWhere('ass.commune = :commune or mam.commune = :commune');
}
$qb->setParameter('commune', $commune);
}
if ($bureauDistributeur) {
$subqueryBuilder = new QueryBuilder($this->getEntityManager());
$subqueryBuilder
->select('bur.id')
->from(BureauDistributeur::class, 'bur')
->andWhere('bur = :bureau_distributeur');
// Cas 1 : lieu d'exercice à domicile uniquement
if ($idLieu & EnumLieuAccueil::DOMICILE && !($idLieu & EnumLieuAccueil::MAM)) {
$subqueryBuilder->andWhere('ass.bureau_distributeur = bur.libelle');
}
// Cas 2 : lieu d'exercice en MAM uniquement
else if ($idLieu & EnumLieuAccueil::MAM && !($idLieu & EnumLieuAccueil::DOMICILE)) {
$subqueryBuilder->andWhere('mam.bureau_distributeur = bur.libelle');
}
// Cas 3 : lieu d'exercice indifférent (ou double agrément)
else {
$subqueryBuilder->andWhere('ass.bureau_distributeur = bur.libelle or mam.bureau_distributeur = bur.libelle');
}
$subquery = $subqueryBuilder->getQuery()->getDQL();
$qb->andWhere($qb->expr()->exists($subquery))
->setParameter('bureau_distributeur', $bureauDistributeur);
}
if ($idLieu) {
//restreint aux assmats avec un agrément existant selon le lieu fourni (pas de contrôle sur la date de fin)
if ($idLieu & EnumLieuAccueil::DOMICILE) {
$qb->andWhere('ass.date_debut_agrement_domicile is not null');
}
if ($idLieu & EnumLieuAccueil::MAM) {
$qb->andWhere('ass.date_debut_agrement_mam is not null');
}
}
if ($formation2 !== null) {
if ($formation2) {
//todo : voir pour la prise en compte de debut d'agrement < 01/01/2007
$qb->andWhere('ass.formation2_effectuee = true');
} else {
$qb->andWhere('ass.formation2_effectuee = false OR ass.formation2_effectuee is null');
}
}
if ($premierAccueil !== null) {
$subqueryBuilder = new QueryBuilder($this->getEntityManager());
$subqueryBuilder
->select('ass.id')
->from(Accueil::class, 'accu')
->andWhere('accu.assmat = ass')
//->andWhere('accu.est_premier_accueil = true ')
->groupBy('ass.id')
->having('count(accu.id) = 1');
$subquery = $subqueryBuilder->getQuery()->getDQL();
if ($premierAccueil) {
$qb->andWhere($qb->expr()->exists($subquery));
} else {
$qb->andWhere($qb->expr()->not($qb->expr()->exists($subquery)));
}
}
if ($offreAccueil !== null) {
if ($offreAccueil) {
// les assmats avec une date de maj ont saisi leur offre d'accueil au moins une fois
$qb->andWhere('ass.date_maj_assmat is not null ');
} else {
$qb->andWhere('ass.date_maj_assmat is null ');
}
}
// resteint aux assmats avec un agrément valide selon la tranche d'âge fournie
if ($trancheAge) {
$subqueryBuilder = new QueryBuilder($this->getEntityManager());
$subqueryBuilder
->select('age.id')
->from(Agrement::class, 'age')
->andWhere('age.assmat = ass');
$subqueryBuilder->andWhere('age.tranche_age = :tranche_age and age.nombre_places > 0 ');
$qb->setParameter('tranche_age', $trancheAge);
$subquery = $subqueryBuilder->getQuery()->getDQL();
$qb->andWhere($qb->expr()->exists($subquery));
/* On n'utilise pas la jointure car on veut charger toute la liste des agréments de l'assmat
* $qb->andWhere('(agr.nombre_places > 0 and agr.tranche_age = :tranche_age)')->setParameter('tranche_age', $trancheAge); */
}
if (!$inclureArchive) {
$critereDomicileValide = ' (ass.archive_domicile = false ) AND (ass.cta_dom is NULL OR ass.cta_dom = false ) AND (ass.suspension_dom is NULL OR ass.suspension_dom = false )';
$critereMamValide = ' (ass.archive_mam = false ) AND (ass.cta_mam is NULL OR ass.cta_mam = false ) AND (ass.suspension_mam is NULL OR ass.suspension_mam = false )';
if ($idLieu) {
//restreint aux assmats avec un agrément valide et non archives selon le lieu fourni
if ($idLieu & EnumLieuAccueil::MAM && $idLieu & EnumLieuAccueil::DOMICILE) {
$qb = $qb->andWhere($critereDomicileValide . 'AND' . $critereMamValide);
} else if ($idLieu & EnumLieuAccueil::DOMICILE) {
$qb = $qb->andWhere($critereDomicileValide);
} else if ($idLieu & EnumLieuAccueil::MAM) {
$qb = $qb->andWhere($critereMamValide);
}
} else {
$qb->andWhere(' (ass.archive_domicile = false OR ass.archive_mam = false )'); //il faut eu moins avoir un des 2 lieux pas archive pour apparaitre
$qb->andWhere(' (ass.cta_dom is NULL OR ass.cta_dom = false )');
$qb->andWhere(' (ass.cta_mam is NULL OR ass.cta_mam = false )');
$qb->andWhere(' (ass.suspension_dom is NULL OR ass.suspension_dom = false )');
$qb->andWhere(' (ass.suspension_mam is NULL OR ass.suspension_mam = false )');
}
$qb->andWhere('(ass.creche is NULL OR ass.creche = false)');
$qb->andWhere('(ass.formation1_effectuee is NULL OR ass.formation1_effectuee = true)');
}
if (!$inclureSupprime) {
$qb->andWhere('ass.supprime = false');
}
if ($listes) {
// affichage listes
\App\Utils\DatatablesUtils::ajouterCritereTri($qb, $paramsDatatable, [
'0' => ['s.libelle'],
'1' => ['ass.nom_famille'],
'2' => ['ass.prenom'],
// Colonne 3 : lieu d'agrément
// On ne peut pas trier server-side, car il n'y a qu'une seule ligne de données par assmat dans la BDD
// alors qu'on en affiche 2 dans l'IHM - les 2 lignes ne peuvent être séparées
// Colonne 4 : adresse, tri pas pertinent
'5' => ['ass.code_postal'],
'6' => ['c.libelle'],
// Colonnes 7 à 18 : non triables
'19' => ['ass.oppose'],
]);
} else {
//critères de tri à affiner
$qb->addSelect('CASE WHEN ass.formation2_effectuee = true THEN 1 '
. 'WHEN ass.formation2_effectuee = false THEN 3 '
. 'ELSE 2 END AS HIDDEN hid_formation2_effectuee ');
$qb->addSelect('CASE WHEN (ass.date_premier_agrement_domicile is not null and ass.date_premier_agrement_mam is not null) '
. 'THEN (CASE WHEN ass.date_premier_agrement_domicile > ass.date_premier_agrement_mam THEN ass.date_premier_agrement_mam ELSE ass.date_premier_agrement_domicile END ) '
. 'WHEN ass.date_premier_agrement_domicile is not null THEN ass.date_premier_agrement_domicile '
. 'WHEN ass.date_premier_agrement_mam is not null THEN ass.date_premier_agrement_mam '
. 'ELSE ass.date_premier_agrement_mam END AS HIDDEN hid_premier_agrem ');
// Recherche assmat
\App\Utils\DatatablesUtils::ajouterCritereTri($qb, $paramsDatatable, [
'0' => ['ass.id_fonctionnel'],
'1' => ['ass.nom_famille', 'ass.prenom'],
'3' => ['hid_formation2_effectuee', 'hid_premier_agrem'],
'4' => ['acc.est_premier_accueil', 'acc.date_derniere_modification']
]);
}
$qb->setFirstResult($paramsDatatable[\App\Utils\DatatablesUtils::START]) // à partir du resultat n° offset
->setMaxResults($paramsDatatable[\App\Utils\DatatablesUtils::LENGTH]); // nb de resultats de la page
$query = $qb->getQuery();
$paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($query);
return $paginator;
}
/**
* Rechercher des dispos assmats selon des critères cumulatifs
* il s'agit des disponibilitésréeles
* @param int? $idCanton
* @param int? $idSecteurPmi
* @param int? $idCommune
* @param ?BureauDistributeur $bureauDistributeur
* @param int? $idLieu
* @param bool $formation2 formation2 effectuée ou pas
* @param array $listeTrancheAge liste des tranches d'ages applicables
* @param bool $inclurePuericultrice indique si les assmats surchargées par la puer doivent faire partie des résultats
* @param utilisateur $puericultrice utilisateur connecté en train de réaliser une recherche
* @param bool $occupeIrreg indique s'il faut considérer les créneaux occupés irrégulièrement comme libres dans la recherche
* @param array $planningDispo planning des dispos libres recherchées
* @param array $paramsDatatable Les paramètres envoyés par Datatables, récupérés avec DatatableUtils
* @return App\Repository\AssistantMaternel
* La liste des assmats renvoyée est triée par nom puis prénom
*/
public function rechercherDispo(
int $idCanton, int $idSecteurPmi, int $idCommune, ?BureauDistributeur $bureauDistributeur, int $idLieu, bool $formation2 = null, $listeTrancheAge = null, bool $inclurePuericultrice, Utilisateur $puericultrice, bool $occupeIrreg, array $planningDispo, array $paramsDatatable
)
{
/* initialise la requête avec un select 'ass' from AssistantMaternel */
$qb = $this->createQueryBuilder('ass')
// Chargement en eager loading car le lazy loading n'est pas possible en OneToOne bidirectionnel
->leftJoin('ass.preferences_publication', 'pref')
->leftJoin('ass.presentation_assmat', 'pres')
->addSelect('pref')
->addSelect('pres')
// optim nombre requetes
->innerJoin('ass.agrements', 'agr')
->andWhere('agr.nombre_places > 0')
->addSelect('agr')
// jointure pour conditions sur la MAM
->leftJoin('ass.mam', 'mam');
if ($listeTrancheAge) {
//nombre de places > 0 pour les tranches d'age cherchées
$qb->andWhere('agr.tranche_age IN (:listeTrancheAge)')
->setParameter('listeTrancheAge', $listeTrancheAge);
}
if ($idCanton != 0) {
$qb->innerJoin('ass.canton', 'can')
->andWhere('can.id = :canton')
->setParameter('canton', $idCanton);
}
if ($idSecteurPmi != 0) {
if ($inclurePuericultrice && $puericultrice != null) {
//on veut à la fois les assmats du secteur et celles de la puer connectée
$qb->innerJoin('ass.secteur_pmi', 'sec')
->andWhere('sec.id = :secteur OR ass.puericultrice = :puericultrice')
->setParameter('secteur', $idSecteurPmi)
->setParameter('puericultrice', $puericultrice);
} else {
//seulement secteur
$qb->innerJoin('ass.secteur_pmi', 'sec')
->andWhere('sec.id = :secteur')
->setParameter('secteur', $idSecteurPmi);
}
}
$qb->leftJoin('ass.commune', 'com')->addSelect('com');
if ($idCommune != 0) {
// FIXME : critère MAM ?
$qb->andWhere('com.id = :commune')->setParameter('commune', $idCommune);
}
if ($bureauDistributeur) {
$subqueryBuilder = new QueryBuilder($this->getEntityManager());
$subqueryBuilder
->select('bur.id')
->from(BureauDistributeur::class, 'bur')
->andWhere('(ass.date_debut_agrement_domicile is not null and ass.bureau_distributeur = bur.libelle)'
. 'or'
. '(ass.date_debut_agrement_mam is not null and mam.bureau_distributeur = bur.libelle)')
->andWhere('bur = :bureau_distributeur');
$subquery = $subqueryBuilder->getQuery()->getDQL();
$qb->andWhere($qb->expr()->exists($subquery))
->setParameter('bureau_distributeur', $bureauDistributeur);
}
$qb->andWhere('(ass.creche is NULL OR ass.creche = false)');
$qb->andWhere('(ass.formation1_effectuee is NULL OR ass.formation1_effectuee = true)');
$critereDomicileValide = ' (ass.archive_domicile = false AND '
. ' ass.date_debut_agrement_domicile is not null AND '
. ' (ass.date_fin_agrement_domicile is null OR ass.date_fin_agrement_domicile > :now ) ) AND '
. ' (ass.cta_dom is NULL OR ass.cta_dom = false ) AND '
. ' (ass.suspension_dom is NULL OR ass.suspension_dom = false )';
$critereMamValide = ' (ass.archive_mam = false AND '
. ' ass.date_debut_agrement_mam is not null AND '
. ' (ass.date_fin_agrement_mam is null OR ass.date_fin_agrement_mam > :now ) ) AND'
. ' (ass.cta_mam is NULL OR ass.cta_mam = false ) AND '
. ' (ass.suspension_mam is NULL OR ass.suspension_mam = false )';
$now = new \DateTime();
if ($idLieu) {
//restreint aux assmats avec un agrément valide et non archives selon le lieu fourni
if (
$idLieu & EnumLieuAccueil::MAM &&
$idLieu & EnumLieuAccueil::DOMICILE
) {
$qb->andWhere($critereDomicileValide . 'AND' . $critereMamValide);
} else if ($idLieu & EnumLieuAccueil::DOMICILE) {
$qb->andWhere($critereDomicileValide);
} else if ($idLieu & EnumLieuAccueil::MAM) {
$qb->andWhere($critereMamValide);
}
} else {
$qb->andWhere('(' . $critereDomicileValide . 'OR' . $critereMamValide . ')');
}
$qb->setParameter('now', $now);
if ($formation2 !== null) {
if ($formation2) {
//todo : voir pour la prise en compte de debut d'agrement < 01/01/2007
$qb->andWhere('ass.formation2_effectuee = true');
} else {
$qb->andWhere('ass.formation2_effectuee = false OR ass.formation2_effectuee is null');
}
}
$qb->andWhere('ass.supprime = false');
if ($planningDispo) {
$idType = 1;
foreach ($planningDispo as $key => $value) {
$subqueryBuilder = new QueryBuilder($this->getEntityManager());
$subqueryBuilder
->select('disp' . $key . '.id')
->from(PlanningDispo::class, 'disp' . $key)
->andWhere('disp' . $key . '.assmat = ass');
if ($value["id_frequence_dispo"] != 1) {
$idPeriode = $value["id_periode"];
$idJour = $value["id_jour_semaine"];
$idHoraire = $value["id_tranche_horaire"];
if ($idLieu != 0) {
$subqueryBuilder->andWhere('disp' . $key . '.lieu_accueil = :idLieu' . $key);
}
$subqueryBuilder->andWhere('disp' . $key . '.type_accueil = :idType' . $key)
->andWhere('disp' . $key . '.periode = :idPeriode' . $key)
->andWhere('disp' . $key . '.tranche_age IN (:listeTrancheAge' . $key . ')')
->andWhere('disp' . $key . '.tranche_horaire = :idHoraire' . $key)
->andWhere('disp' . $key . '.jour_semaine = :idJour' . $key);
if ($idLieu != 0) {
$qb->setParameter('idLieu' . $key, $idLieu);
}
$qb->setParameter('idType' . $key, $idType)
->setParameter('listeTrancheAge' . $key, $listeTrancheAge)
->setParameter('idPeriode' . $key, $idPeriode)
->setParameter('idJour' . $key, $idJour)
->setParameter('idHoraire' . $key, $idHoraire);
if ($occupeIrreg) {
$subqueryBuilder->andWhere('disp' . $key . '.nombre_places_libres_irregulier > 0');
} else {
$subqueryBuilder->andWhere('disp' . $key . '.nombre_places_libres > 0');
}
$subquery = $subqueryBuilder->getQuery()->getDQL();
$qb->andWhere($qb->expr()->exists($subquery));
}
}
}
\App\Utils\DatatablesUtils::ajouterCritereTri($qb, $paramsDatatable, [
'0' => ['ass.id_fonctionnel'],
'1' => ['ass.nom_famille', 'ass.prenom'],
'2' => ['ass.code_postal']
]);
$qb->setFirstResult($paramsDatatable[\App\Utils\DatatablesUtils::START]) // à partir du resultat n° offset
->setMaxResults($paramsDatatable[\App\Utils\DatatablesUtils::LENGTH]); // nb de resultats de la page
$query = $qb->getQuery();
$paginator = new \Doctrine\ORM\Tools\Pagination\Paginator($query);
return $paginator;
}
/**
* Rechercher des dispos assmats selon des critères cumulatifs
* @param int? $idCommune
* @param int? $idBureauDistributeur
* @param int? $idLieu
* @param array $listeTrancheAge liste des tranches d'ages applicables
* @param bool $atypiqueMatin indique s'il faut inclure les assmats acceptant les accueils atypiques le matin
* @param bool $atypiqueSoir indique s'il faut inclure les assmats acceptant les accueils atypiques le soir
* @param bool $handicap indique s'il faut inclure les assmats acceptant les enfants en situation de handicap
* @param array $planningDispo planning des dispos libres recherchées
* @param bool $participe indique si les assmats recherchées participent ou non au site grand public
* @param $listeIdASM restreint les résultats aux AM de la liste
* @param $listeIdMAM restreint les résultats aux AM qui font partie des MAM de la liste
* @return App\Repository\AssistantMaternel
* La liste des assmats renvoyée est triée par nom puis prénom
*/
public function rechercherDispoGrandPublic(
int $idCommune, int $idBureauDistributeur, int $idLieu, $listeTrancheAge = null,
bool $atypiqueMatin = null, bool $atypiqueSoir = null, bool $handicap = null,
array $planningDispo, bool $participe, $listeIdASM = null, $listeIdMAM = null
)
{
/* initialise la requête avec un select 'ass' from AssistantMaternel */
$qb = $this->createQueryBuilder('ass')
// Chargement en eager loading car le lazy loading n'est pas possible en OneToOne bidirectionnel
->leftJoin('ass.preferences_publication', 'pref')
->leftJoin('ass.presentation_assmat', 'pres')
->addSelect('pref')->addSelect('pres')
// optim nombre requetes
->innerJoin('ass.agrements', 'agr')
->andWhere('agr.nombre_places > 0')
->addSelect('agr');
if ($listeIdASM != null && count($listeIdASM) > 0) {
$listeIdASM = array_map('strval', $listeIdASM);
if(count($listeIdASM) > 0) {
$qb = $qb->andWhere("ass.id_fonctionnel IN (:listeIdASM)")
->setParameter('listeIdASM', $listeIdASM, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
}
}
if ($listeIdMAM != null && count($listeIdMAM) > 0) {
$listeIdMAM = array_map('strval', $listeIdMAM);
if(count($listeIdMAM) > 0) {
$qb = $qb->leftJoin('ass.mam', 'mam')
->addSelect('mam');
$qb = $qb->andWhere("mam.id_fonctionnel IN (:listeIdMAM)")
->setParameter('listeIdMAM', $listeIdMAM, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
}
}
//nombre de places > 0 pour les tranches d'age cherchées
$qb = $qb->andWhere('agr.tranche_age IN (:listeTrancheAge)')
->setParameter('listeTrancheAge', $listeTrancheAge);
if ($idCommune != 0) {
$qb = $qb->innerJoin('ass.commune', 'com')
->andWhere('com.id = :commune')
->setParameter('commune', $idCommune);
}
if ($idBureauDistributeur != 0) {
// FIXME
$qb = $qb->from(BureauDistributeur::class, 'bur')
->andWhere('ass.bureau_distributeur = bur.libelle')
->andWhere('bur.id = :bureau_distributeur')
->setParameter('bureau_distributeur', $idBureauDistributeur);
}
$qb->andWhere('(ass.creche is NULL OR ass.creche = false)');
$qb->andWhere('(ass.formation1_effectuee is NULL OR ass.formation1_effectuee = true)');
$critereDomicileValide = ' (ass.archive_domicile = false AND '
. ' ass.date_debut_agrement_domicile is not null AND '
. ' (ass.date_fin_agrement_domicile is null OR ass.date_fin_agrement_domicile > :now ) ) AND '
. ' (ass.cta_dom is NULL OR ass.cta_dom = false ) AND '
. ' (ass.suspension_dom is NULL OR ass.suspension_dom = false )';
$critereMamValide = ' (ass.archive_mam = false AND '
. ' ass.date_debut_agrement_mam is not null AND '
. ' (ass.date_fin_agrement_mam is null OR ass.date_fin_agrement_mam > :now ) ) AND'
. ' (ass.cta_mam is NULL OR ass.cta_mam = false ) AND '
. ' (ass.suspension_mam is NULL OR ass.suspension_mam = false )';
$now = new \DateTime();
$qb = $qb->setParameter('now', $now);
if ($idLieu) {
//restreint aux assmats avec un agrément valide et non archives selon le lieu fourni
if (
$idLieu & EnumLieuAccueil::MAM &&
$idLieu & EnumLieuAccueil::DOMICILE
) {
$qb = $qb->andWhere($critereDomicileValide . 'AND' . $critereMamValide);
} else if ($idLieu & EnumLieuAccueil::DOMICILE) {
$qb = $qb->andWhere($critereDomicileValide);
} else if ($idLieu & EnumLieuAccueil::MAM) {
$qb = $qb->andWhere($critereMamValide);
}
} else {
$qb = $qb->andWhere('(' . $critereDomicileValide . 'OR' . $critereMamValide . ')');
}
// seulement les assmats non supprimés
$qb = $qb->andWhere('ass.supprime = false');
//TODO : lien avec offre accueil
if ($handicap !== null && $handicap) {
$qb = $qb->andWhere('pres.accepte_handicap = true');
}
if ($atypiqueMatin !== null && $atypiqueMatin) {
$qb = $qb->andWhere('pres.accepte_atypique_matin = true');
}
if ($atypiqueSoir !== null && $atypiqueSoir) {
$qb = $qb->andWhere('pres.accepte_atypique_soir = true');
}
if ($participe !== null) {
//les assmats qui rempli leur calendrier de dispo publiques
$subqExistDispoBuilder = new QueryBuilder($this->getEntityManager());
$subqExistDispoBuilder
->select('dispo.id')
->from(DispoPublicAssmat::class, 'dispo')
->andWhere('dispo.assmat = ass');
if ($idLieu != 0) {
$subqExistDispoBuilder->andWhere('dispo.lieu_accueil = :idLieu');
$qb->setParameter('idLieu', $idLieu);
}
$subqExistDispo = $subqExistDispoBuilder->getQuery()->getDQL();
// prise en compte des 'participe' sur présence d'un planning de dispo seulement
if ($participe) {
$qb->andWhere($qb->expr()->exists($subqExistDispo));
} else {
$qb->andWhere($qb->expr()->not($qb->expr()->exists($subqExistDispo)));
}
}
if ($participe) {
if ($planningDispo) {
$idType = 1;
foreach ($planningDispo as $key => $value) {
$subqueryBuilder = new QueryBuilder($this->getEntityManager());
$subqueryBuilder
->select('disp' . $key . '.id')
->from(DispoPublicAssmat::class, 'disp' . $key)
->andWhere('disp' . $key . '.assmat = ass');
if ($value["id_frequence_dispo"] != 1) {
$idPeriode = $value["id_periode"];
$idJour = $value["id_jour_semaine"];
$idHoraire = $value["id_tranche_horaire"];
if ($idLieu != 0) {
$subqueryBuilder->andWhere('disp' . $key . '.lieu_accueil = :idLieu' . $key);
}
$subqueryBuilder->andWhere('disp' . $key . '.type_accueil = :idType' . $key)
->andWhere('disp' . $key . '.periode = :idPeriode' . $key)
->andWhere('disp' . $key . '.tranche_age IN (:listeTrancheAge' . $key . ')')
->andWhere('disp' . $key . '.tranche_horaire = :idHoraire' . $key)
->andWhere('disp' . $key . '.jour_semaine = :idJour' . $key);
if ($idLieu != 0) {
$qb->setParameter('idLieu' . $key, $idLieu);
}
$qb->setParameter('idType' . $key, $idType)
->setParameter('listeTrancheAge' . $key, $listeTrancheAge)
->setParameter('idPeriode' . $key, $idPeriode)
->setParameter('idJour' . $key, $idJour)
->setParameter('idHoraire' . $key, $idHoraire);
$subqueryBuilder->andWhere('disp' . $key . '.nombre_places_libres > 0');
$subquery = $subqueryBuilder->getQuery()->getDQL();
$qb->andWhere($qb->expr()->exists($subquery));
}
}
}
//sinon, pas de planning fourni => toutes les assmats ayant saisi un planing de dispo remontent (même celles jamais dispos)
}
//on ne doit pas prendre en compte les assmats opposées au site grand public
$qb = $qb->andWhere('ass.oppose = false');
$query = $qb->orderBy('ass.nom_famille', 'ASC')
->addOrderBy('ass.prenom', 'ASC')
->getQuery();
//TODO : si besoin de paginer
//->setFirstResult( $offset ) // à partir du resultat n° offset
//->setMaxResults( $limit ) // nb de resultats de la page
return $query->getResult();
}
/**
* Rechercher des dispos grand public prévisionnelles assmats selon des critères cumulatifs
* @param int? $idCommune
* @param int? $idBureauDistributeur
* @param int? $idLieu
* @param array $listeTrancheAge liste des tranches d'ages applicables
* @param \DateTime $dateDebutAccueil date de début de la recherche de disponibilité prévisionnelle
* @param bool $atypiqueMatin indique s'il faut inclure les assmats acceptant les accueils atypiques le matin
* @param bool $atypiqueSoir indique s'il faut inclure les assmats acceptant les accueils atypiques le soir
* @param bool $handicap indique s'il faut inclure les assmats acceptant les enfants en situation de handicap
* @param bool $participe indique si les assmats recherchées participent ou non au site grand public
* @return App\Repository\AssistantMaternel
* La liste des assmats renvoyée est triée par nom puis prénom
*/
public function rechercherDispoPrevGrandPublic(
int $idCommune, int $idBureauDistributeur, int $idLieu, $listeTrancheAge = null, $dateDebutAccueil, bool $atypiqueMatin = null, bool $atypiqueSoir = null, bool $handicap = null, bool $participe, $listeIdASM = null
)
{
/* initialise la requête avec un select 'ass' from AssistantMaternel */
$qb = $this->createQueryBuilder('ass')
// Chargement en eager loading car le lazy loading n'est pas possible en OneToOne bidirectionnel
->leftJoin('ass.preferences_publication', 'pref')
->leftJoin('ass.presentation_assmat', 'pres')
->leftJoin('ass.dispos_prev', 'prev')
->addSelect('pref')->addSelect('pres')
// optim nombre requetes
->innerJoin('ass.agrements', 'agr')
->andWhere('agr.nombre_places > 0')
->addSelect('agr');
if ($listeIdASM != null && count($listeIdASM) > 0) {
$listeIdASM = array_map('strval', $listeIdASM);
$qb = $qb->andWhere("ass.id_fonctionnel IN (:listeIdASM)")
->setParameter('listeIdASM', $listeIdASM, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
}
//nombre de places > 0 pour les tranches d'age cherchées
$qb = $qb->andWhere('agr.tranche_age IN (:listeTrancheAge)')
->setParameter('listeTrancheAge', $listeTrancheAge);
// existe des dispos prev pour les tranches d'age cherchées
$qb = $qb->andWhere('prev.tranche_age IN (:listeTrancheAge)')
->setParameter('listeTrancheAge', $listeTrancheAge);
if ($dateDebutAccueil != null) {
$qb = $qb->andWhere('prev.date_debut <= :dateDebutAccueil')
->setParameter('dateDebutAccueil', $dateDebutAccueil);
}
if ($idCommune != 0) {
$qb = $qb->innerJoin('ass.commune', 'com')
->andWhere('com.id = :commune')
->setParameter('commune', $idCommune);
}
if ($idBureauDistributeur != 0) {
$qb = $qb->from(BureauDistributeur::class, 'bur')
->andWhere('ass.bureau_distributeur = bur.libelle')
->andWhere('bur.id = :bureau_distributeur')
->setParameter('bureau_distributeur', $idBureauDistributeur);
}
$qb->andWhere('(ass.creche is NULL OR ass.creche = false)');
$qb->andWhere('(ass.formation1_effectuee is NULL OR ass.formation1_effectuee = true)');
$critereDomicileValide = ' (ass.archive_domicile = false AND '
. ' ass.date_debut_agrement_domicile is not null AND '
. ' (ass.date_fin_agrement_domicile is null OR ass.date_fin_agrement_domicile > :now ) ) AND '
. ' (ass.cta_dom is NULL OR ass.cta_dom = false ) AND '
. ' (ass.suspension_dom is NULL OR ass.suspension_dom = false )';
$critereMamValide = ' (ass.archive_mam = false AND '
. ' ass.date_debut_agrement_mam is not null AND '
. ' (ass.date_fin_agrement_mam is null OR ass.date_fin_agrement_mam > :now ) ) AND'
. ' (ass.cta_mam is NULL OR ass.cta_mam = false ) AND '
. ' (ass.suspension_mam is NULL OR ass.suspension_mam = false )';
$now = new \DateTime();
$qb = $qb->setParameter('now', $now);
if ($idLieu) {
//restreint aux assmats avec un agrément valide et non archives selon le lieu fourni
if (
$idLieu & EnumLieuAccueil::MAM &&
$idLieu & EnumLieuAccueil::DOMICILE
) {
$qb = $qb->andWhere($critereDomicileValide . 'AND' . $critereMamValide);
} else if ($idLieu & EnumLieuAccueil::DOMICILE) {
$qb = $qb->andWhere($critereDomicileValide);
} else if ($idLieu & EnumLieuAccueil::MAM) {
$qb = $qb->andWhere($critereMamValide);
}
$qb = $qb->andWhere('prev.lieu_accueil = :idLieu')
->setParameter('idLieu', $idLieu);
} else {
$qb = $qb->andWhere($critereDomicileValide . 'OR' . $critereMamValide);
}
// seulement les assmats non supprimés
$qb = $qb->andWhere('ass.supprime = false');
//TODO : lien avec offre accueil
if ($handicap !== null && $handicap) {
$qb = $qb->andWhere('pres.accepte_handicap = true');
}
if ($atypiqueMatin !== null && $atypiqueMatin) {
$qb = $qb->andWhere('pres.accepte_atypique_matin = true');
}
if ($atypiqueSoir !== null && $atypiqueSoir) {
$qb = $qb->andWhere('pres.accepte_atypique_soir = true');
}
if ($participe !== null) {
//les assmats avec participe à true ont rempli leur calendrier de dispo publiques
if ($participe) {
$qb = $qb->andWhere('ass.participe = true');
} else {
$qb = $qb->andWhere('ass.participe = false OR ass.participe is null');
}
}
//on ne doit pas prendre en compte les assmats opposées au site grand public
$qb = $qb->andWhere('ass.oppose = false');
$query = $qb->getQuery();
return $query->getResult();
}
/**
*/
public function getAllIterable()
{
// TODO doc
return $this->createQueryBuilder('ass')->addOrderBy('ass.id', 'ASC')->getQuery()->iterate();
}
public function findSansCompteUtilisateur($limiteComptesAssmats = null)
{
$qb = $this->createQueryBuilder('ass')
->where('ass.utilisateur is null');
if ($limiteComptesAssmats) {
$qb->setMaxResults($limiteComptesAssmats);
}
// TODO doc
return $qb->getQuery()->iterate();
}
}