Skip to content
Snippets Groups Projects
Select Git revision
  • fe3fa288c801fcf90f99012da47ae3318d145478
  • master default protected
2 results

jquery.min.js

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    ServiceService.php 52.79 KiB
    <?php
    
    namespace Application\Service;
    
    use Application\Entity\Db\ElementPedagogique;
    use Application\Entity\Db\Etablissement;
    use Application\Entity\Db\Etape;
    use Application\Entity\Db\EtatVolumeHoraire;
    use Application\Entity\Db\Intervenant;
    use Application\Entity\Db\Service;
    use Application\Entity\Db\Structure;
    use Application\Entity\Db\TypeIntervention;
    use Application\Entity\Db\TypeIntervenant;
    use Application\Entity\Db\TypeVolumeHoraire;
    use Application\Entity\NiveauEtape;
    use Application\Entity\Service\Recherche;
    use Application\Form\Service\RechercheHydrator;
    use Application\Hydrator\Service\Traits\RechercheHydratorAwareTrait;
    use Application\Provider\Privilege\Privileges;
    use Application\Service\Traits\ElementPedagogiqueServiceAwareTrait;
    use Application\Service\Traits\EtapeServiceAwareTrait;
    use Application\Service\Traits\IntervenantServiceAwareTrait;
    use Application\Service\Traits\LocalContextServiceAwareTrait;
    use Application\Service\Traits\PeriodeServiceAwareTrait;
    use Application\Service\Traits\SourceServiceAwareTrait;
    use Application\Service\Traits\StatutIntervenantServiceAwareTrait;
    use Application\Service\Traits\StructureServiceAwareTrait;
    use Application\Service\Traits\TypeIntervenantServiceAwareTrait;
    use Application\Service\Traits\TypeInterventionServiceAwareTrait;
    use Application\Service\Traits\TypeVolumeHoraireServiceAwareTrait;
    use Application\Service\Traits\ValidationServiceAwareTrait;
    use Application\Service\Traits\VolumeHoraireServiceAwareTrait;
    use Application\Service\Traits\EtatVolumeHoraireServiceAwareTrait;
    use Doctrine\ORM\QueryBuilder;
    use Zend\Session\Container as SessionContainer;
    
    /**
     * Description of Service
     *
     * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
     *
     * @method Service get($id)
     * @method Service[] getList(\Doctrine\ORM\QueryBuilder $qb = null, $alias = null)
     *
     */
    class ServiceService extends AbstractEntityService
    {
        use ElementPedagogiqueServiceAwareTrait;
        use EtapeServiceAwareTrait;
        use IntervenantServiceAwareTrait;
        use StructureServiceAwareTrait;
        use TypeInterventionServiceAwareTrait;
        use EtatVolumeHoraireServiceAwareTrait;
        use TypeVolumeHoraireServiceAwareTrait;
        use VolumeHoraireServiceAwareTrait;
        use TypeIntervenantServiceAwareTrait;
        use PeriodeServiceAwareTrait;
        use LocalContextServiceAwareTrait;
        use RechercheHydratorAwareTrait;
        use ValidationServiceAwareTrait;
        use StatutIntervenantServiceAwareTrait;
        use SourceServiceAwareTrait;
    
        /**
         *
         * @var SessionContainer
         */
        private $rechercheSessionContainer;
    
        /**
         *
         * @var Recherche
         */
        private $recherche;
    
    
    
        /**
         * retourne la classe des entités
         *
         * @return string
         * @throws RuntimeException
         */
        public function getEntityClass()
        {
            return Service::class;
        }
    
    
    
        /**
         * Retourne l'alias d'entité courante
         *
         * @return string
         */
        public function getAlias()
        {
            return 's';
        }
    
    
    
        /**
         * Retourne une nouvelle entité de la classe donnée
         *
         * @return Service
         */
        public function newEntity()
        {
            $entity = parent::newEntity();
    
            $role = $this->getServiceContext()->getSelectedIdentityRole();
            if ($intervenant = $role->getIntervenant()) {
                $entity->setIntervenant($intervenant);
            }
    
            return $entity;
        }
    
    
    
        /**
         *
         * @return SessionContainer
         */
        protected function getRechercheSessionContainer()
        {
            if (null === $this->rechercheSessionContainer) {
                $this->rechercheSessionContainer = new SessionContainer(get_class($this) . '_Recherche');
            }
    
            return $this->rechercheSessionContainer;
        }
    
    
    
        /**
         * Les paramètres de recherche sont également remplis à l'aide du contexte local
         *
         * @return Recherche
         */
        public function loadRecherche()
        {
            if (null === $this->recherche) {
                $this->recherche = new Recherche;
                $session         = $this->getRechercheSessionContainer();
                if ($session->offsetExists('data')) {
                    $this->getHydratorServiceRecherche()->hydrate($session->data, $this->recherche);
                }
            }
    
            if (!$this->recherche->getTypeVolumeHoraire()) {
                $this->recherche->setTypeVolumeHoraire($this->getServiceTypeVolumeHoraire()->getPrevu());
            }
    
            if (!$this->recherche->getEtatVolumeHoraire()) {
                $this->recherche->setEtatVolumeHoraire($this->getServiceEtatVolumeHoraire()->getSaisi());
            }
    
            $localContext = $this->getServiceLocalContext();
    
            $this->recherche->setIntervenant($localContext->getIntervenant());
            $this->recherche->setStructureEns($localContext->getStructure());
            $this->recherche->setNiveauEtape($localContext->getNiveau());
            $this->recherche->setEtape($localContext->getEtape());
            $this->recherche->setElementPedagogique($localContext->getElementPedagogique());
    
            return $this->recherche;
        }
    
    
    
        /**
         * Les paramètres de recherche sont également sauvegardés dans le contexte local
         *
         * @param Recherche $recherche
         *
         * @return self
         */
        public function saveRecherche(Recherche $recherche)
        {
            if ($recherche !== $this->recherche) {
                $this->recherche = $recherche;
            }
            $data          = $this->getHydratorServiceRecherche()->extract($recherche);
            $session       = $this->getRechercheSessionContainer();
            $session->data = $data;
    
            $localContext = $this->getServiceLocalContext();
    
            $localContext->setIntervenant($recherche->getIntervenant());
            $localContext->setStructure($recherche->getStructureEns());
            $localContext->setNiveau($recherche->getNiveauEtape());
            $localContext->setEtape($recherche->getEtape());
            $localContext->setElementPedagogique($recherche->getElementPedagogique());
    
            return $this;
        }
    
    
    
        /**
         * Retourne un service unique selon ses critères précis
         *
         * @param Intervenant              $intervenant
         * @param ElementPedagogique $elementPedagogique
         * @param Etablissement      $etablissement
         *
         * @return null|Service
         */
        public function getBy(
            Intervenant $intervenant,
            $elementPedagogique,
            Etablissement $etablissement
        )
        {
            $result = $this->getRepo()->findBy([
                'intervenant'        => $intervenant,
                'elementPedagogique' => $elementPedagogique,
                'etablissement'      => $etablissement,
            ]);
    
            if (count($result) > 1) {
                foreach ($result as $sr) {
                    /* @var $sr \Application\Entity\Db\Service */
                    if ($sr->estNonHistorise()) return $sr;
                }
    
                return $result[0]; // sinon retourne le premier trouvé...
            } elseif (isset($result[0])) {
                return $result[0];
            } else {
                return null;
            }
        }
    
    
    
        /**
         * Sauvegarde une entité
         *
         * @param Service $entity
         *
         * @throws Exception
         * @return Service
         */
        public function save($entity)
        {
            $this->getEntityManager()->getConnection()->beginTransaction();
            try {
                $role = $this->getServiceContext()->getSelectedIdentityRole();
    
                if (!$entity->getEtablissement()) {
                    $entity->setEtablissement($this->getServiceContext()->getEtablissement());
                    if (!$entity->getEtablissement()){
                        throw new \LogicException('L\'établissement n\'est pas renseigné dans les paramétrages généraux de OSE');
                    }
                }
                if (!$entity->getIntervenant() && $intervenant = $role->getIntervenant()) {
                    $entity->setIntervenant($intervenant);
                }
                if (!$this->getAuthorize()->isAllowed($entity, Privileges::ENSEIGNEMENT_EDITION)) {
                    throw new \BjyAuthorize\Exception\UnAuthorizedException('Saisie interdite');
                }
    
                $serviceAllreadyExists = null;
                if (!$entity->getId()) { // uniquement pour les nouveaux services!!
                    $serviceAllreadyExists = $this->getBy(
                        $entity->getIntervenant(),
                        $entity->getElementPedagogique(),
                        $entity->getEtablissement()
                    );
                }
                if ($serviceAllreadyExists) {
                    $result = $serviceAllreadyExists;
                } else {
                    if ($entity->hasChanged()) {
                        $sourceOse = $this->getServiceSource()->getOse();
                        if (!$entity->getSource()){
                            $entity->setSource($sourceOse);
                        }
                        if (!$entity->getSourceCode()){
                            $entity->setSourceCode(uniqid('ose-'));
                        }
                        foreach( $entity->getVolumeHoraire() as $vh ){
                            if (!$vh->getSource()){
                                $vh->setSource($sourceOse);
                            }
                            if (!$vh->getSourceCode()){
                                $vh->setSourceCode(uniqid('ose-'));
                            }
                        }
    
                        $result = parent::save($entity);
                        $entity->setChanged(false);
                    } else {
                        $result = $entity;
                    }
                }
    
                /* Sauvegarde automatique des volumes horaires associés */
                $serviceVolumeHoraire = $this->getServiceVolumeHoraire();
                foreach ($entity->getVolumeHoraire() as $volumeHoraire) {
                    /* @var $volumeHoraire \Application\Entity\Db\Volumehoraire */
                    if ($result !== $entity) $volumeHoraire->setService($result);
                    if ($volumeHoraire->getRemove()) {
                        $serviceVolumeHoraire->delete($volumeHoraire);
                    } else {
                        $serviceVolumeHoraire->save($volumeHoraire, false); // pas de contrôle de plafond sur le VH ! ! !
                    }
                }
                $this->getEntityManager()->getConnection()->commit();
            } catch (Exception $e) {
                $this->getEntityManager()->getConnection()->rollBack();
                throw $e;
            }
    
            return $result;
        }
    
    
    
        /**
         * Supprime (historise par défaut) le service spécifié.
         *
         * @param Service $entity Entité à détruire
         * @param bool    $softDelete
         *
         * @return self
         */
        public function delete($entity, $softDelete = true)
        {
            if ($softDelete) {
                $vhListe = $entity->getVolumeHoraireListe();
                foreach ($vhListe->getPeriodes() as $periode) {
                    $lc = $vhListe->getChild()->setPeriode($periode);
                    foreach ($lc->getTypesIntervention() as $typeIntervention) {
                        $lc->getChild()->setTypeIntervention($typeIntervention)->setHeures(0);
                    }
                }
            }
            //$vhListe->setHeures(0); // aucune heure (SI une heure est validée alors un nouveau VHR sera créé!!
    
            $vhl = $entity->getVolumeHoraire();
    
            $delete = true;
            /** @var VolumeHoraireService $volumeHoraire */
            foreach ($vhl as $volumeHoraire) {
                if ($volumeHoraire->getRemove() || !$volumeHoraire->estNonHistorise()) {
                    $this->getServiceVolumeHoraire()->delete($volumeHoraire, $softDelete);
                    $vhl->removeElement($volumeHoraire);
                } else {
                    $delete = false;
                    $this->getServiceVolumeHoraire()->save($volumeHoraire);
                }
            }
    
            if ($delete) {
                parent::delete($entity, $softDelete);
            }
    
            return $this;
        }
    
    
    
        /**
         * Retourne la liste des services selon l'étape donnée
         *
         * @param Etape       $etape
         * @param QueryBuilder|null $queryBuilder
         *
         * @return QueryBuilder
         */
        public function finderByEtape(Etape $etape, QueryBuilder $qb = null, $alias = null)
        {
            $serviceElement = $this->getServiceElementPedagogique();
    
            list($qb, $alias) = $this->initQuery($qb, $alias);
            $this->leftJoin($serviceElement, $qb, 'elementPedagogique');
            $serviceElement->finderByEtape($etape, $qb);
    
            return $qb;
        }
    
    
    
        /**
         * Retourne la liste des services selon l'étape donnée
         *
         * @param Etape       $etape
         * @param QueryBuilder|null $queryBuilder
         *
         * @return QueryBuilder
         */
        public function finderByNiveauEtape(NiveauEtape $niveauEtape, QueryBuilder $qb = null, $alias = null)
        {
            list($qb, $alias) = $this->initQuery($qb, $alias);
            if ($niveauEtape && $niveauEtape->getId() !== '-') {
                $serviceElement = $this->getServiceElementPedagogique();
                $serviceEtape   = $this->getServiceEtape();
    
                $this->leftJoin($serviceElement, $qb, 'elementPedagogique');
                $serviceElement->join($serviceEtape, $qb, 'etape');
                $serviceEtape->finderByNiveau($niveauEtape, $qb);
            }
    
            return $qb;
        }
    
    
    
        /**
         *
         * @param TypeVolumeHoraire $typeVolumeHoraire
         * @param QueryBuilder      $qb
         * @param string            $alias
         *
         * @return QueryBuilder
         */
        public function finderByTypeVolumeHoraire(TypeVolumeHoraire $typeVolumeHoraire, QueryBuilder $qb = null, $alias = null)
        {
            list($qb, $alias) = $this->initQuery($qb, $alias);
            if ($typeVolumeHoraire) {
                $serviceVolumeHoraire = $this->getServiceVolumeHoraire();
    
                $this->join($serviceVolumeHoraire, $qb, 'volumeHoraire');
                $serviceVolumeHoraire->finderByTypeVolumeHoraire($typeVolumeHoraire, $qb);
            }
    
            return $qb;
        }
    
    
    
        /**
         *
         * @param EtatVolumeHoraire $etatVolumeHoraire
         * @param QueryBuilder      $qb
         * @param string            $alias
         *
         * @return QueryBuilder
         */
        public function finderByEtatVolumeHoraire(EtatVolumeHoraire $etatVolumeHoraire, QueryBuilder $qb = null, $alias = null)
        {
            list($qb, $alias) = $this->initQuery($qb, $alias);
            if ($etatVolumeHoraire) {
                $serviceVolumeHoraire = $this->getServiceVolumeHoraire();
    
                $this->join($serviceVolumeHoraire, $qb, 'volumeHoraire');
                $serviceVolumeHoraire->finderByEtatVolumeHoraire($etatVolumeHoraire, $qb);
            }
    
            return $qb;
        }
    
    
    
        /**
         * Retourne le query builder permettant de rechercher les services prévisionnels
         * selon la composante spécifiée.
         *
         * Càd les services prévisionnels satisfaisant au moins l'un des critères suivants :
         * - la structure d'enseignement (champ 'structure_ens') est la structure spécifiée;
         * - la structure d'affectation (champ 'structure_aff')  est la structure spécifiée;
         *
         * @param Structure         $structure
         * @param QueryBuilder|null $queryBuilder
         *
         * @return QueryBuilder
         */
        public function finderByComposante(Structure $structure, QueryBuilder $qb = null, $alias = null)
        {
            list($qb, $alias) = $this->initQuery($qb, $alias);
    
            $serviceStructure          = $this->getServiceStructure();
            $serviceIntervenant        = $this->getServiceIntervenant();
            $serviceElementPedagogique = $this->getServiceElementPedagogique();
            $serviceStatutIntervenant  = $this->getServiceStatutIntervenant();
            $iAlias                    = $serviceIntervenant->getAlias();
            $sAlias                    = $serviceStatutIntervenant->getAlias();
    
            $this->join($serviceIntervenant, $qb, 'intervenant', false, $alias);
            $serviceIntervenant->join($serviceStatutIntervenant, $qb, 'statut', false);
            $this->leftJoin($serviceElementPedagogique, $qb, 'elementPedagogique', false, $alias);
            $serviceElementPedagogique->leftJoin($serviceStructure, $qb, 'structure', false, null, 's_ens');
    
            $filter = "(($sAlias.typeIntervenant = :typeIntervenantPermanent AND $iAlias.structure = :composante) OR s_ens = :composante)";
            $qb->andWhere($filter)->setParameter('composante', $structure);
            $qb->setParameter('typeIntervenantPermanent', $this->getServiceTypeIntervenant()->getPermanent());
    
            return $qb;
        }
    
    
    
        /**
         * Utile pour la recherche de services
         *
         * @param Structure         $structure
         * @param QueryBuilder|null $queryBuilder
         *
         * @return QueryBuilder
         */
        public function finderByStructureAff(Structure $structure, QueryBuilder $qb = null, $alias = null)
        {
            list($qb, $alias) = $this->initQuery($qb, $alias);
    
            $serviceIntervenant = $this->getServiceIntervenant();
    
            $this->join($serviceIntervenant, $qb, 'intervenant', false, $alias);
            $serviceIntervenant->finderByStructure($structure, $qb);
            $serviceIntervenant->finderByType($this->getServiceTypeIntervenant()->getPermanent(), $qb);
    
            return $qb;
        }
    
    
    
        /**
         * Utile pour la recherche de services
         *
         * @param Structure         $structure
         * @param QueryBuilder|null $queryBuilder
         *
         * @return QueryBuilder
         */
        public function finderByStructureEns(Structure $structure, QueryBuilder $qb = null, $alias = null)
        {
            list($qb, $alias) = $this->initQuery($qb, $alias);
    
            $serviceElementPedagogique = $this->getServiceElementPedagogique();
            $this->join($serviceElementPedagogique, $qb, 'elementPedagogique', false, $alias);
            $serviceElementPedagogique->finderByStructure($structure, $qb);
    
            return $qb;
        }
    
    
    
        /**
         * Filtre la liste des services selon lecontexte courant
         *
         * @param QueryBuilder|null $qb
         * @param string|null       $alias
         *
         * @return QueryBuilder
         */
        public function finderByContext(QueryBuilder $qb = null, $alias = null)
        {
            $role = $this->getServiceContext()->getSelectedIdentityRole();
    
            list($qb, $alias) = $this->initQuery($qb, $alias);
    
            $this->join($this->getServiceIntervenant(), $qb, 'intervenant', false, $alias);
            $this->getServiceIntervenant()->finderByAnnee($this->getServiceContext()->getAnnee(), $qb);
    
            if ($intervenant = $role->getIntervenant()) { // Si c'est un intervenant
                $this->finderByIntervenant($intervenant, $qb, $alias);
            }
    
            return $qb;
        }
    
    
    
        /**
         * Retourne la liste des services selon l'étape donnée
         *
         * @param TypeIntervenant   $typeIntervenant
         * @param QueryBuilder|null $queryBuilder
         *
         * @return QueryBuilder
         */
        public function finderByTypeIntervenant(TypeIntervenant $typeIntervenant = null, QueryBuilder $qb = null, $alias = null)
        {
            list($qb, $alias) = $this->initQuery($qb, $alias);
            if ($typeIntervenant) {
                $this->join($this->getServiceIntervenant(), $qb, 'intervenant', false, $alias);
                $this->getServiceIntervenant()->finderByType($typeIntervenant, $qb);
            }
    
            return $qb;
        }
    
    
    
        /**
         * Prend les services d'un intervenant, année n-1, et reporte ces services (et les volumes horaires associés)
         * sur l'année n
         *
         * @param Intervenant $intervenant
         *
         */
        public function setPrevusFromPrevus(Intervenant $intervenant)
        {
            $old               = $this->getPrevusFromPrevusData($intervenant);
            $typeVolumeHoraire = $this->getServiceTypeVolumeHoraire()->getPrevu();
    
            // Enregistrement des services trouvés dans la nouvelle année
            foreach ($old as $o) {
                $service = $o['service'];
                if (!$service) {
                    $service = $this->newEntity();
                    $service->setIntervenant($intervenant);
                    $service->setElementPedagogique($o['element-pedagogique']);
                    $service->setEtablissement($o['etablissement']);
                }
                foreach ($o['heures'] as $heures) {
                    $volumeHoraire = $this->getServiceVolumeHoraire()->newEntity();
                    //@formatter:off
                    $volumeHoraire->setTypeVolumeHoraire( $heures['type-volume-horaire'] );
                    $volumeHoraire->setPeriode          ( $heures['periode']             );
                    $volumeHoraire->setTypeIntervention ( $heures['type-intervention']   );
                    $volumeHoraire->setHeures           ( $heures['heures']              );
                    //@formatter:on
                    $volumeHoraire->setService($service);
                    $service->addVolumeHoraire($volumeHoraire);
                }
                $service->setHistoDestructeur(null); // restauration du service si besoin!!
                $service->setHistoDestruction(null);
                $service->setTypeVolumeHoraire($typeVolumeHoraire);
                $this->save($service, false);
            }
        }
    
    
    
        public function getPrevusFromPrevusData(Intervenant $intervenant)
        {
            $tvhPrevu  = $this->getServiceTypeVolumeHoraire()->getPrevu();
            $evhValide = $this->getServiceEtatVolumeHoraire()->getValide();
    
            $intervenantPrec = $this->getServiceIntervenant()->getBySourceCode(
                $intervenant->getSourceCode(),
                $this->getServiceContext()->getAnneePrecedente(),
                false
            );
    
            $sVolumeHoraire = $this->getServiceVolumeHoraire();
    
            $qb = $this->select(['id', 'elementPedagogique', 'etablissement']);
            //@formatter:off
            $this->join(    EtablissementService::class,                     $qb, 'etablissement',           true);//['id', 'sourceCode']);
            $this->leftJoin(ElementPedagogiqueService::class,                $qb, 'elementPedagogique',      true);//['id', 'sourceCode']);
            $this->leftJoin($sVolumeHoraire,                                $qb, 'volumeHoraire',           true);//['id', 'periode', 'typeIntervention', 'heures']);
            $sVolumeHoraire->leftJoin(PeriodeService::class,                 $qb, 'periode',                 true);//['id']);
            $sVolumeHoraire->leftJoin(TypeInterventionService::class,        $qb, 'typeIntervention',        true);//['id']);
            //@formatter:on
    
            $this->finderByHistorique($qb);
            $this->finderByIntervenant($intervenantPrec, $qb);
            $sVolumeHoraire->finderByHistorique($qb);
            $sVolumeHoraire->finderByTypeVolumeHoraire($tvhPrevu, $qb);
            $sVolumeHoraire->finderByEtatVolumeHoraire($evhValide, $qb);
    
            $s = $this->getList($qb);
    
            $old = [];
            foreach ($s as $service) {
    
                /* @var $service \Application\Entity\Db\Service */
                $service->setTypeVolumeHoraire($tvhPrevu);
                $oldElement = $service->getElementPedagogique();
                $newElement = $oldElement ? $this->getServiceElementPedagogique()->getBySourceCode(
                    $oldElement->getSourceCode(),
                    $this->getServiceContext()->getAnnee()
                ) : null;
    
                if ($newElement && !$newElement->estNonHistorise()) {
                    $newElement = null; // s'il n'est pas actif alors on ne reporte pas
                }
    
                $newPeriode = $newElement ? $newElement->getPeriode() : null;
    
                if (empty($oldElement) || !empty($newElement)) {
                    $o  = [
                        'element-pedagogique' => $newElement,
                        'etablissement'       => $service->getEtablissement(),
                        'heures'              => [],
                    ];
                    $id = $newElement ? $newElement->getSourceCode() : '';
                    $id .= '-';
                    $id .= $service->getEtablissement()->getSourceCode();
    
                    $vhl = $service->getVolumeHoraireListe();
    
                    $periodes          = $vhl->getPeriodes();
                    $typesIntervention = $vhl->getTypesIntervention();
                    foreach ($periodes as $periode) {
                        /* @var $periode \Application\Entity\Db\Periode */
                        if (empty($newPeriode) || $periode === $newPeriode) { // pas de mauvaise période!!!
                            foreach ($typesIntervention as $typeIntervention) {
                                /* @var $typeIntervention TypeInterventionService */
                                $heures = $vhl->setPeriode($periode)->setTypeIntervention($typeIntervention)->getHeures();
                                if ($heures > 0) {
                                    $o['heures'][] = [
                                        'periode'             => $periode,
                                        'type-intervention'   => $typeIntervention,
                                        'type-volume-horaire' => $tvhPrevu,
                                        'heures'              => $heures,
                                    ];
                                }
                            }
                        }
                    }
    
                    if (!empty($o['heures'])) {
                        $newService = $this->getBy($intervenant, $newElement, $service->getEtablissement());
                        if ($newService) {
                            $newService->setTypeVolumeHoraire($tvhPrevu);
                        }
                        if ($newService && $newService->estNonHistorise()) {
                            $newHeures = $newService->getVolumeHoraireListe()->getHeures();
                        } else {
                            $newHeures = 0;
                        }
                        if ($newHeures == 0) { // on n'insère pas le service si des heures ont déjà été saisies!!
                            $o['service'] = $newService;
                            $old[$id]     = $o;
                        }
                    }
                }
            }
    
            return $old;
        }
    
    
    
        public function setRealisesFromPrevus(Service $service)
        {
            $prevus = $service
                ->getVolumeHoraireListe()->getChild()
                ->setTypeVolumeHoraire($this->getServiceTypeVolumeHoraire()->getPrevu())
                ->setEtatVolumeHoraire($this->getServiceEtatVolumeHoraire()->getValide());
    
            $realises = $service
                ->getVolumeHoraireListe()->getChild()
                ->setTypeVolumeHoraire($this->getServiceTypeVolumeHoraire()->getRealise())
                ->setEtatVolumeHoraire($this->getServiceEtatVolumeHoraire()->getSaisi());
    
            $typesIntervention = $prevus->getTypesIntervention() + $realises->getTypesIntervention();
            $periodes          = $prevus->getPeriodes() + $realises->getPeriodes();
    
            foreach ($periodes as $periode) {
                $prevus->setPeriode($periode);
                $realises->setPeriode($periode);
                foreach ($typesIntervention as $typeIntervention) {
                    $prevus->setTypeIntervention($typeIntervention);
                    $realises->setTypeIntervention($typeIntervention);
    
                    $realises->setHeures($prevus->getHeures());
                }
            }
            $this->save($service);
        }
    
    
    
        /**
         * Retourne les données du TBL des services en fonction des critères de recherche transmis
         *
         * @param Recherche $recherche
         *
         * @return array
         */
        public function getTableauBord(Recherche $recherche, array $options = [])
        {
            // initialisation
            $defaultOptions    = [
                'tri'              => 'intervenant',   // [intervenant, hetd]
                'columns'          => [],              // Liste des colonnes utiles, hors colonnes liées aux types d'intervention!!
                'ignored-columns'  => [],              // Liste des colonnes à ne pas récupérer, hors colonnes liées aux types d'intervention!!
                'isoler-non-payes' => true,            // boolean
                'regroupement'     => 'service',       // [service, intervenant]
                'composante'       => null,            // Composante qui en fait la demande
            ];
            $options           = array_merge($defaultOptions, $options);
            $annee             = $this->getServiceContext()->getAnnee();
            $data              = [];
            $shown             = [];
            $typesIntervention = [];
            $invertTi          = [];
            $numericColunms    = [
                'service-statutaire',
                'service-du-modifie',
                'heures-non-payees',
                'heures-ref',
                'service-fi',
                'service-fa',
                'service-fc',
                'service-referentiel',
                'heures-compl-fi',
                'heures-compl-fa',
                'heures-compl-fc',
                'heures-compl-fc-majorees',
                'heures-compl-referentiel',
                'total',
                'solde',
            ];
            $dateColumns       = [
                'service-date-modification',
                'intervenant-date-naissance',
                'date-cloture-service-realise',
            ];
            $addableColumns    = [
                '__total__',
                'heures-non-payees',
                'heures-ref',
                'service-fi',
                'service-fa',
                'service-fc',
                'service-referentiel',
                'heures-compl-fi',
                'heures-compl-fa',
                'heures-compl-fc',
                'heures-compl-fc-majorees',
                'heures-compl-referentiel',
                'total',
            ];
    
            // requêtage
            $conditions = [
                'annee_id = ' . $annee->getId(),
            ];
            if ($c1 = $recherche->getTypeVolumeHoraire()) $conditions['type_volume_horaire_id'] = '(type_volume_horaire_id = -1 OR type_volume_horaire_id = ' . $c1->getId() . ')';
            if ($c2 = $recherche->getEtatVolumeHoraire()) $conditions['etat_volume_horaire_id'] = '(etat_volume_horaire_id = -1 OR etat_volume_horaire_id = ' . $c2->getId() . ')';
            if ($c3 = $recherche->getTypeIntervenant()) $conditions['type_intervenant_id'] = '(type_intervenant_id = -1 OR type_intervenant_id = ' . $c3->getId() . ')';
            if ($c4 = $recherche->getIntervenant()) $conditions['intervenant_id'] = '(intervenant_id = -1 OR intervenant_id = ' . $c4->getId() . ')';
            //if ($c5 = $recherche->getNiveauFormation()    ) $conditions['niveau_formation_id']    = '(niveau_formation_id = -1 OR niveau_formation_id = '    . $c5->getId().')';
            if ($c6 = $recherche->getEtape()) $conditions['etape_id'] = '(etape_id = -1 OR etape_id = ' . $c6->getId() . ')';
            if ($c7 = $recherche->getElementPedagogique()) $conditions['element_pedagogique_id'] = '(element_pedagogique_id = -1 OR element_pedagogique_id = ' . $c7->getId() . ')';
            if ($c8 = $recherche->getStructureAff()) $conditions['structure_aff_id'] = '(structure_aff_id = -1 OR structure_aff_id = ' . $c8->getId() . ')';
            if ($c9 = $recherche->getStructureEns()) $conditions['structure_ens_id'] = '(structure_ens_id = -1 OR structure_ens_id = ' . $c9->getId() . ')';
    
            if ($options['composante'] instanceof Structure) {
                $id                       = (int)$options['composante']->getId();
                $conditions['composante'] = "(structure_aff_id = -1 OR structure_aff_id = $id OR structure_ens_id = -1 OR structure_ens_id = $id)";
            }
    
            switch ($options['tri']) {
                case 'intervenant':
                    $orderBy = 'INTERVENANT_NOM, SERVICE_STRUCTURE_AFF_LIBELLE, SERVICE_STRUCTURE_ENS_LIBELLE, ETAPE_LIBELLE, ELEMENT_LIBELLE';
                break;
                case 'hetd':
                    $orderBy = 'SOLDE, INTERVENANT_NOM, SERVICE_STRUCTURE_AFF_LIBELLE, SERVICE_STRUCTURE_ENS_LIBELLE, ETAPE_LIBELLE, ELEMENT_LIBELLE';
                break;
                default:
                    $orderBy = 'INTERVENANT_NOM, SERVICE_STRUCTURE_AFF_LIBELLE, SERVICE_STRUCTURE_ENS_LIBELLE, ETAPE_LIBELLE, ELEMENT_LIBELLE';
                break;
            }
    
            $sql  = 'SELECT * FROM V_EXPORT_SERVICE WHERE ' . implode(' AND ', $conditions) . ' '
                . 'ORDER BY ' . $orderBy;
            $stmt = $this->getEntityManager()->getConnection()->executeQuery($sql);
    
            $dateExtraction = new \DateTime();
    
            // récupération des données
            while ($d = $stmt->fetch()) {
    
                if ($options['isoler-non-payes'] && (int)$d['HEURES_NON_PAYEES'] === 1) {
                    $d['HEURES_NON_PAYEES'] = $d['HEURES'];
                    $d['HEURES']            = 0;
                }
    
                if ('intervenant' === $options['regroupement']) {
                    $sid = $d['INTERVENANT_ID'];
                } else {
                    $sid = $d['SERVICE_ID'] ? $d['SERVICE_ID'] . '_' . $d['PERIODE_ID'] : $d['ID'];
                }
                $ds = [
                    '__total__'                 => (float)$d['HEURES'] + (float)$d['HEURES_NON_PAYEES'] + (float)$d['HEURES_REF'] + (float)$d['TOTAL'],
                    'type-etat'                 => $d['TYPE_ETAT'],
                    'date'                      => $dateExtraction,
                    'service-date-modification' => $d['SERVICE_DATE_MODIFICATION'],
                    'annee-libelle'             => (string)$annee,
    
                    'intervenant-code'               => $d['INTERVENANT_CODE'],
                    'intervenant-nom'                => $d['INTERVENANT_NOM'],
                    'intervenant-date-naissance'     => $d['INTERVENANT_DATE_NAISSANCE'],
                    'intervenant-statut-libelle'     => $d['INTERVENANT_STATUT_LIBELLE'],
                    'intervenant-type-code'          => $d['INTERVENANT_TYPE_CODE'],
                    'intervenant-type-libelle'       => $d['INTERVENANT_TYPE_LIBELLE'],
                    'intervenant-grade-code'         => $d['INTERVENANT_GRADE_CODE'],
                    'intervenant-grade-libelle'      => $d['INTERVENANT_GRADE_LIBELLE'],
                    'intervenant-discipline-code'    => $d['INTERVENANT_DISCIPLINE_CODE'],
                    'intervenant-discipline-libelle' => $d['INTERVENANT_DISCIPLINE_LIBELLE'],
                    'heures-service-statutaire'      => (float)$d['SERVICE_STATUTAIRE'],
                    'heures-service-du-modifie'      => (float)$d['SERVICE_DU_MODIFIE'],
                    'service-structure-aff-libelle'  => $d['SERVICE_STRUCTURE_AFF_LIBELLE'],
    
                    'service-structure-ens-libelle' => $d['SERVICE_STRUCTURE_ENS_LIBELLE'],
                    'groupe-type-formation-libelle' => $d['GROUPE_TYPE_FORMATION_LIBELLE'],
                    'type-formation-libelle'        => $d['TYPE_FORMATION_LIBELLE'],
                    'etape-niveau'                  => empty($d['ETAPE_NIVEAU']) ? null : (int)$d['ETAPE_NIVEAU'],
                    'etape-code'                    => $d['ETAPE_CODE'],
                    'etape-etablissement-libelle'   => $d['ETAPE_LIBELLE'] ? $d['ETAPE_LIBELLE'] : ($d['SERVICE_REF_FORMATION'] ? $d['SERVICE_REF_FORMATION'] : $d['ETABLISSEMENT_LIBELLE']),
                    'element-code'                  => $d['ELEMENT_CODE'],
                    'element-fonction-libelle'      => $d['ELEMENT_LIBELLE'] ? $d['ELEMENT_LIBELLE'] : $d['FONCTION_REFERENTIEL_LIBELLE'],
                    'element-discipline-code'       => $d['ELEMENT_DISCIPLINE_CODE'],
                    'element-discipline-libelle'    => $d['ELEMENT_DISCIPLINE_LIBELLE'],
                    'element-taux-fi'               => (float)$d['ELEMENT_TAUX_FI'],
                    'element-taux-fc'               => (float)$d['ELEMENT_TAUX_FC'],
                    'element-taux-fa'               => (float)$d['ELEMENT_TAUX_FA'],
                    'commentaires'                  => $d['COMMENTAIRES'],
                    'element-ponderation-compl'     => $d['ELEMENT_PONDERATION_COMPL'] === null ? null : (float)$d['ELEMENT_PONDERATION_COMPL'],
                    'element-source-libelle'        => $d['ELEMENT_SOURCE_LIBELLE'],
    
                    'periode-libelle'              => $d['PERIODE_LIBELLE'],
                    'heures-non-payees'            => (float)$d['HEURES_NON_PAYEES'],
                    // types d'intervention traités en aval
                    'heures-ref'                   => (float)$d['HEURES_REF'],
                    'service-fi'                   => (float)$d['SERVICE_FI'],
                    'service-fa'                   => (float)$d['SERVICE_FA'],
                    'service-fc'                   => (float)$d['SERVICE_FC'],
                    'service-referentiel'          => (float)$d['SERVICE_REFERENTIEL'],
                    'heures-compl-fi'              => (float)$d['HEURES_COMPL_FI'],
                    'heures-compl-fa'              => (float)$d['HEURES_COMPL_FA'],
                    'heures-compl-fc'              => (float)$d['HEURES_COMPL_FC'],
                    'heures-compl-fc-majorees'     => (float)$d['HEURES_COMPL_FC_MAJOREES'],
                    'heures-compl-referentiel'     => (float)$d['HEURES_COMPL_REFERENTIEL'],
                    'total'                        => (float)$d['TOTAL'],
                    'solde'                        => (float)$d['SOLDE'],
                    'date-cloture-service-realise' => $d['DATE_CLOTURE_REALISE'],
                ];
    
                if (
                    $ds['heures-service-statutaire'] > 0
                    && $ds['heures-service-statutaire'] + $ds['heures-service-du-modifie'] == 0
                    && empty($ds['etape-code'])
                ) {
                    $ds['__total__']++; // pour que le cas spécifique des décharges totales soit pris en compte
                }
    
                if ($d['TYPE_INTERVENTION_ID'] != null) {
                    $tid = $d['TYPE_INTERVENTION_ID'];
                    if (!isset($typesIntervention[$tid])) {
                        $typesIntervention[$tid] = $this->getServiceTypeIntervention()->get($tid);
                    }
                    $typeIntervention                                              = $typesIntervention[$tid];
                    $invertTi['type-intervention-' . $typeIntervention->getCode()] = $typeIntervention->getId();
                    $ds['type-intervention-' . $typeIntervention->getCode()]       = (float)$d['HEURES'];
                }
                foreach ($ds as $column => $value) {
                    if (empty($options['columns']) || in_array($column, $options['columns']) || 0 === strpos($column, 'type-intervention-')) {
                        if (!isset($shown[$column])) $shown[$column] = 0;
                        if (is_float($value)) {
                            $shown[$column] += $value;
                        } else {
                            $shown[$column] += empty($value) ? 0 : 1;
                        }
                    }
                    if (in_array($column, $options['ignored-columns'])) {
                        $shown[$column] = 0;
                    }
                }
                if (!isset($data[$sid])) {
                    $data[$sid] = $ds;
                } else {
                    foreach ($ds as $column => $value) {
                        if (empty($options['columns']) || in_array($column, $options['columns']) || 0 === strpos($column, 'type-intervention-')) {
                            if (in_array($column, $addableColumns) || 0 === strpos($column, 'type-intervention-')) {
                                if (!isset($data[$sid][$column])) {
                                    $data[$sid][$column] = $value;
                                } // pour les types d'intervention no initialisés
                                else $data[$sid][$column] += $value;
                            } elseif ($value != $data[$sid][$column]) {
                                $data[$sid][$column] = null;
                            }
                        }
                    }
                }
            }
    
            // tri et préparation des entêtes
            $head = [
                'type-etat'                 => 'Type État',
                'date'                      => 'Date d\'extraction',
                'annee-libelle'             => 'Année universitaire',
                'service-date-modification' => 'Date de modif. du service',
    
                'intervenant-code'               => 'Code intervenant',
                'intervenant-nom'                => 'Intervenant',
                'intervenant-date-naissance'     => 'Date de naissance',
                'intervenant-statut-libelle'     => 'Statut intervenant',
                'intervenant-type-code'          => 'Type d\'intervenant (Code)',
                'intervenant-type-libelle'       => 'Type d\'intervenant',
                'intervenant-grade-code'         => 'Grade (Code)',
                'intervenant-grade-libelle'      => 'Grade',
                'intervenant-discipline-code'    => 'Discipline intervenant (Code)',
                'intervenant-discipline-libelle' => 'Discipline intervenant',
                'heures-service-statutaire'      => 'Service statutaire',
                'heures-service-du-modifie'      => 'Modification de service du',
                'service-structure-aff-libelle'  => 'StructureService d\'affectation',
    
                'service-structure-ens-libelle' => 'StructureService d\'enseignement',
                'groupe-type-formation-libelle' => 'Groupe de type de formation',
                'type-formation-libelle'        => 'Type de formation',
                'etape-niveau'                  => 'Niveau',
                'etape-code'                    => 'Code formation',
                'etape-etablissement-libelle'   => 'Formation ou établissement',
                'element-code'                  => 'Code enseignement',
                'element-fonction-libelle'      => 'Enseignement ou fonction référentielle',
                'element-discipline-code'       => 'Discipline ens. (Code)',
                'element-discipline-libelle'    => 'Discipline ens.',
                'element-taux-fi'               => 'Taux FI',
                'element-taux-fc'               => 'Taux FC',
                'element-taux-fa'               => 'Taux FA',
                'commentaires'                  => 'Commentaires',
                'element-ponderation-compl'     => 'Majoration',
                'element-source-libelle'        => 'SourceService enseignement',
                'periode-libelle'               => 'Période',
                'heures-non-payees'             => 'Heures non payées',
            ];
            uasort($typesIntervention, function ($ti1, $ti2) {
                return $ti1->getOrdre() > $ti2->getOrdre();
            });
            foreach ($typesIntervention as $typeIntervention) {
                /* @var $typeIntervention \Application\Entity\Db\TypeIntervention */
                $head['type-intervention-' . $typeIntervention->getCode()] = $typeIntervention->getCode();
            }
            $head['heures-ref']                   = 'Référentiel';
            $head['service-fi']                   = 'HETD Service FI';
            $head['service-fa']                   = 'HETD Service FA';
            $head['service-fc']                   = 'HETD Service FC';
            $head['service-referentiel']          = 'HETD Service Référentiel';
            $head['heures-compl-fi']              = 'HETD Compl. FI';
            $head['heures-compl-fa']              = 'HETD Compl. FA';
            $head['heures-compl-fc']              = 'HETD Compl. FC';
            $head['heures-compl-fc-majorees']     = 'HETD Compl. FC D714-60';
            $head['heures-compl-referentiel']     = 'HETD Compl. référentiel';
            $head['total']                        = 'Total HETD';
            $head['solde']                        = 'Solde HETD';
            $head['date-cloture-service-realise'] = 'Clôture du service réalisé';
    
            // suppression des informations superflues
            foreach ($shown as $column => $visibility) {
                if (isset($head[$column]) && empty($visibility)) {
                    unset($head[$column]);
                    if (isset($invertTi[$column])) {
                        unset($typesIntervention[$invertTi[$column]]);
                    }
                }
            }
            $columns = array_keys($head);
            foreach ($data as $sid => $d) {
                if (0 == $d['__total__']) {
                    unset($data[$sid]); // pas d'affichage pour quelqu'un qui n'a rien
                } else {
                    $data[$sid] = [];
                    foreach ($columns as $column) {
                        $value = isset($d[$column]) ? $d[$column] : null;
                        if (null === $value && (in_array($column, $numericColunms) || 0 === strpos($column, 'type-intervention-'))) {
                            $value = 0;
                        }
    
                        if (in_array($column, $dateColumns)) {
                            if (empty($value)) $value = null; else $value = \DateTime::createFromFormat('Y-m-d', substr($value, 0, 10));
                        }
    
                        $data[$sid][$column] = $value;
                    }
                }
            }
    
            return [
                'head'               => $head,
                'data'               => $data,
                'types-intervention' => $typesIntervention,
            ];
        }
    
    
    
        /**
         * Retourne les données du TBL des services en fonction des critères de recherche transmis
         *
         * @param Recherche $recherche
         *
         * @return array
         */
        public function getExportPdfData(Recherche $recherche)
        {
            $annee = $this->getServiceContext()->getAnnee();
            $data  = [
                'intervenants' => [],
                'total'        => [
                    'fi'          => 0,
                    'fa'          => 0,
                    'fc'          => 0,
                    'referentiel' => 0,
                    'total'       => 0,
                ],
            ];
    
            // requêtage
            $conditions = [
                'annee_id = ' . $annee->getId(),
            ];
            if ($c1 = $recherche->getTypeVolumeHoraire()) $conditions['type_volume_horaire_id'] = '(es.type_volume_horaire_id = -1 OR es.type_volume_horaire_id = ' . $c1->getId() . ')';
            if ($c2 = $recherche->getEtatVolumeHoraire()) $conditions['etat_volume_horaire_id'] = '(es.etat_volume_horaire_id = -1 OR es.etat_volume_horaire_id = ' . $c2->getId() . ')';
            if ($c3 = $recherche->getTypeIntervenant()) $conditions['type_intervenant_id'] = '(es.type_intervenant_id = -1 OR es.type_intervenant_id = ' . $c3->getId() . ')';
            if ($c4 = $recherche->getIntervenant()) $conditions['intervenant_id'] = '(es.intervenant_id = -1 OR es.intervenant_id = ' . $c4->getId() . ')';
            //if ($c5 = $recherche->getNiveauFormation()    ) $conditions['niveau_formation_id']    = '(es.niveau_formation_id = -1 OR es.niveau_formation_id = '    . $c5->getId().')';
            if ($c6 = $recherche->getEtape()) $conditions['etape_id'] = '(es.etape_id = -1 OR etape_id = ' . $c6->getId() . ')';
            if ($c7 = $recherche->getElementPedagogique()) $conditions['element_pedagogique_id'] = '(es.element_pedagogique_id = -1 OR es.element_pedagogique_id = ' . $c7->getId() . ')';
            if ($c8 = $recherche->getStructureAff()) $conditions['structure_aff_id'] = '(es.structure_aff_id = -1 OR es.structure_aff_id = ' . $c8->getId() . ')';
            if ($c9 = $recherche->getStructureEns()) $conditions['structure_ens_id'] = '(es.structure_ens_id = -1 OR es.structure_ens_id = ' . $c9->getId() . ')';
    
            $sql   = '
              SELECT 
                es.*, 
                COALESCE(fsm.heures,0) modifications_service_du 
              FROM 
                V_EXPORT_SERVICE es
                LEFT JOIN V_FORMULE_SERVICE_MODIFIE fsm ON fsm.intervenant_id = es.intervenant_id
              WHERE 
                ' . implode(' AND ', $conditions) . '
              ORDER BY 
                INTERVENANT_NOM, 
                SERVICE_STRUCTURE_ENS_LIBELLE, 
                ETAPE_LIBELLE, ETABLISSEMENT_LIBELLE,
                ELEMENT_LIBELLE, FONCTION_REFERENTIEL_LIBELLE
            ';
            $stmt  = $this->getEntityManager()->getConnection()->executeQuery($sql);
            $count = 0;
            // récupération des données
            while ($d = $stmt->fetch()) {
                $count++;
                $iid = (int)$d['INTERVENANT_ID'];
                $sid = (int)$d['SERVICE_ID'];
    
                if (!isset($data['intervenants'][$iid])) {
                    $data['intervenants'][$iid] = [
                        'nom'              => $d['INTERVENANT_NOM'],
                        'statut'           => $d['INTERVENANT_STATUT_LIBELLE'],
                        'grade'            => $d['INTERVENANT_GRADE_LIBELLE'],
                        'service-du'       => (float)$d['SERVICE_STATUTAIRE'],
                        'modif-service-du' => (float)$d['MODIFICATIONS_SERVICE_DU'],
                        'fi'               => 0,
                        'fa'               => 0,
                        'fc'               => 0,
                        'referentiel'      => 0,
                        'total'            => 0,
                        'solde'            => (float)$d['SOLDE'],
                        'services'         => [],
                    ];
                }
    
                if (!isset($data['intervenants'][$iid]['services'][$sid])) {
                    $data['intervenants'][$iid]['services'][$sid] = [
                        'structure'      => $d['SERVICE_STRUCTURE_ENS_LIBELLE'],
                        'type-formation' => $d['TYPE_FORMATION_LIBELLE'],
                        'formation'      => $d['ETAPE_LIBELLE'] ? $d['ETAPE_LIBELLE'] : $d['ETABLISSEMENT_LIBELLE'],
                        'enseignement'   => $d['ELEMENT_LIBELLE'] ? $d['ELEMENT_LIBELLE'] : $d['FONCTION_REFERENTIEL_LIBELLE'],
                        'fi'             => 0,
                        'fa'             => 0,
                        'fc'             => 0,
                        'referentiel'    => 0,
                        'total'          => 0,
                    ];
                }
    
                $fi    = (float)$d['SERVICE_FI'] + (float)$d['HEURES_COMPL_FI'];
                $fa    = (float)$d['SERVICE_FA'] + (float)$d['HEURES_COMPL_FA'];
                $fc    = (float)$d['SERVICE_FC'] + (float)$d['HEURES_COMPL_FC'] + (float)$d['HEURES_COMPL_FC_MAJOREES'];
                $ref   = (float)$d['SERVICE_REFERENTIEL'] + (float)$d['HEURES_COMPL_REFERENTIEL'];
                $total = $fi + $fa + $fc + $ref;
    
                $data['total']['fi']          += $fi;
                $data['total']['fa']          += $fa;
                $data['total']['fc']          += $fc;
                $data['total']['referentiel'] += $ref;
                $data['total']['total']       += $total;
    
                $data['intervenants'][$iid]['fi']          += $fi;
                $data['intervenants'][$iid]['fa']          += $fa;
                $data['intervenants'][$iid]['fc']          += $fc;
                $data['intervenants'][$iid]['referentiel'] += $ref;
                $data['intervenants'][$iid]['total']       += $total;
    
                $data['intervenants'][$iid]['services'][$sid]['fi']          += $fi;
                $data['intervenants'][$iid]['services'][$sid]['fa']          += $fa;
                $data['intervenants'][$iid]['services'][$sid]['fc']          += $fc;
                $data['intervenants'][$iid]['services'][$sid]['referentiel'] += $ref;
                $data['intervenants'][$iid]['services'][$sid]['total']       += $total;
            }
    
            $lim = 10000;
    
            if ($count > $lim) {
                die('La génération du fichier est impossible : trop de données ( ' . $count . ' lignes pour ' . $lim . ' autorisées) sont remontées. Merci de placer un filtre (composante, type d\'intervenant, etc)');
            }
    
            return $data;
        }
    
    
    
        /**
         * Détermine si un service est assuré localement (c'est-à-dire dans l'université) ou sur un autre établissement
         *
         * @param \Application\Entity\Db\Service $service
         *
         * @return boolean
         */
        protected function isLocal(Service $service)
        {
            if (!$service->getEtablissement()) return true; // par défaut
            if ($service->getEtablissement() === $this->getServiceContext()->getEtablissement()) return true;
    
            return false;
        }
    
    
    
        /**
         * Retourne la période courante d'un service
         *
         * @param \Application\Entity\Db\Service $service
         *
         * @return \Application\Entity\Db\Periode
         */
        public function getPeriode(Service $service)
        {
            if (!$this->isLocal($service)) return null;
            if (!$service->getElementPedagogique()) return null;
    
            return $service->getElementPedagogique()->getPeriode();
        }
    
    
    
        /**
         *
         * @param \Application\Entity\Db\Service $service
         *
         * @return \Application\Entity\Db\Periode[]
         */
        public function getPeriodes(Service $service)
        {
            $p = $this->getPeriode($service);
            if (null === $p) {
                // Pas de période donc toutes les périodes sont autorisées
                return $this->getServicePeriode()->getEnseignement();
            } else {
                return [$p->getId() => $p];
            }
        }
    
    
    
        /**
         *
         * @param Service|Service[] $services
         *
         * @return TypeIntervention[]
         */
        public function getTypesIntervention($services)
        {
            if ($services instanceof Service) $services = [$services];
            $typesIntervention = [];
            foreach ($services as $service) {
                if (!$service instanceof Service) {
                    throw new \LogicException('Seules des entités Service doivent être passées en paramètre');
                }
                if ($ep = $service->getElementPedagogique()) {
                    foreach ($ep->getTypeIntervention() as $typeIntervention) {
                        $typesIntervention[$typeIntervention->getId()] = $typeIntervention;
                    }
                }
            }
            usort($typesIntervention, function ($ti1, $ti2) {
                return $ti1->getOrdre() > $ti2->getOrdre();
            });
    
            return $typesIntervention;
        }
    
    
    
        /**
         * Retourne le total HETD des enseignements (réalisés et validés) d'un intervenant.
         *
         * @prama Intervenant $intervenant
         * @return float
         */
        public function getTotalHetdIntervenant(Intervenant $intervenant)
        {
            $typeVolumeHoraire = $this->getServiceTypeVolumeHoraire()->getRealise();
            $etatVolumeHoraire = $this->getServiceEtatVolumeHoraire()->getValide();
    
            $fr = $intervenant->getUniqueFormuleResultat($typeVolumeHoraire, $etatVolumeHoraire);
    
            return $fr->getServiceDu() + $fr->getSolde();
        }
    
    
    
        /**
         *
         * @param Service[]   $services
         * @param TypeVolumeHoraire $typeVolumehoraire
         */
        public function setTypeVolumehoraire($services, TypeVolumeHoraire $typeVolumeHoraire)
        {
            foreach ($services as $service) {
                $service->setTypeVolumeHoraire($typeVolumeHoraire);
            }
        }
    }