+++ /dev/null
-/*
- * Copyright © FYLAB and the Conseil Régional d'Île-de-France, 2009
- * This file is part of L'Interface Libre et Interactive de l'Enseignement (Lilie).
- *
- * Lilie is free software. You can redistribute it and/or modify since
- * you respect the terms of either (at least one of the both license) :
- * - under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- * - the CeCILL-C as published by CeCILL-C; either version 1 of the
- * License, or any later version
- *
- * There are special exceptions to the terms and conditions of the
- * licenses as they are applied to this software. View the full text of
- * the exception in file LICENSE.txt in the directory of this software
- * distribution.
- *
- * Lilie is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Licenses for more details.
- *
- * You should have received a copy of the GNU General Public License
- * and the CeCILL-C along with Lilie. If not, see :
- * <http://www.gnu.org/licenses/> and
- * <http://www.cecill.info/licences.fr.html>.
- */
-
-package org.lilie.services.eliot.notes.notes
-
-import org.lilie.services.eliot.scolarite.Enseignement
-import org.lilie.services.eliot.scolarite.Periode
-import org.lilie.services.eliot.scolarite.Service
-import org.lilie.services.eliot.securite.AutorisationException
-import org.lilie.services.eliot.securite.impl.Autorite
-import org.lilie.services.eliot.exception.SauvegardeEchoueException
-import org.hibernate.FetchMode
-import org.lilie.services.eliot.exception.SuppresionEchoueException
-import org.lilie.services.eliot.scolarite.Etablissement
-import org.lilie.services.eliot.applications.notes.EvaluationService
-import org.lilie.services.eliot.notes.scolarite.NotesEnseignementService
-import org.lilie.services.eliot.notes.resultat.UptodateService
-import org.lilie.services.eliot.notes.Evaluation
-import org.lilie.services.eliot.notes.Note
-import org.lilie.services.eliot.scolarite.SousService
-import org.lilie.services.eliot.scolarite.TypePeriode
-import org.lilie.services.eliot.notes.scolarite.NotesTypePeriodeService
-import org.lilie.services.eliot.notes.scolarite.NotesPeriodeService
-import org.springframework.context.ApplicationContext
-import org.springframework.context.ApplicationContextAware
-import org.lilie.services.eliot.notes.scolarite.NotesSousServiceService
-import org.lilie.services.eliot.notes.exception.PeriodeVerrouilleException
-import org.lilie.services.eliot.notes.NotesDroitService
-import org.lilie.services.eliot.notes.ActionEnum
-import org.hibernate.exception.ConstraintViolationException
-import org.lilie.services.eliot.annuaire.SecuriteSession
-import org.lilie.services.eliot.notes.utils.NotesHibernateSessionService
-import org.lilie.services.eliot.scolarite.ModaliteMatiere
-import org.lilie.services.eliot.notes.exception.NoteMaxNonValideException
-import org.lilie.services.eliot.notes.exception.NoteMaxSurpasseeException
-import org.lilie.services.eliot.notes.NotesFonction
-
-/**
- * Service sur les évaluations
- * @author fsil
- * @author msan
- */
-class NotesEvaluationService extends EvaluationService implements ApplicationContextAware {
-
- static transactional = true
-
- // ApplicationContext est aussi un service singleton
- @SuppressWarnings('GrailsStatelessService')
- ApplicationContext applicationContext
-
- NotesDroitService notesDroitService
- NotesEnseignementService notesEnseignementService
- UptodateService uptodateService
- NoteService noteService
- NotesTypePeriodeService notesTypePeriodeService
- NotesHibernateSessionService notesHibernateSessionService
-
- /**
- * Retourne les Evaluations si le service est évaluable pour le type de période
- * donné et le type équivalent. Les notes sont retournées uniquement pour les
- * sous-services évaluables.
- * @author msan
- * @author bper
- */
- List<Evaluation> findAllEvaluations(SecuriteSession securiteSession,
- Service service,
- TypePeriode typePeriode,
- Autorite enseignant,
- Etablissement etab)
- throws AutorisationException, IllegalArgumentException {
-
- notesDroitService.verifieAutorisationByEtablissement(
- securiteSession,
- etab,
- ActionEnum.CONSULTATION,
- (List) (NotesFonction.ENSEIGNANT_ASSIMILE +
- NotesFonction.DIRECTION_ASSIMILE
- )
- )
-
- if (typePeriode == null) {
- throw new IllegalArgumentException(
- "La valeur null pour le paramètre {typePeriode} n'est pas acceptée"
- )
- }
-
- if (service == null) {
- throw new IllegalArgumentException(
- "La valeur null pour le paramètre {service} n'est pas acceptée"
- )
- }
-
- if (enseignant == null) {
- throw new IllegalArgumentException(
- "La valeur null pour le paramètre {enseignant} n'est pas acceptée"
- )
- }
-
- Enseignement enseignement = notesEnseignementService.findEnseignement(
- service,
- enseignant
- )
-
- if (enseignement == null) {
- throw new IllegalStateException(
- "Enseignement n'existe pas pour [service: $service enseignant: $enseignant]"
- )
- }
-
- TypePeriode typePeriodeEquiv =
- notesTypePeriodeService.getTypePeriodeEquivalent(typePeriode)
-
- // Dans le cas où le service n'est pas évaluable pour les deux types de périodes
- // retourne liste vide
- if (!service.isEvaluable(typePeriode)) {
- if (typePeriodeEquiv) {
- if (!service.isEvaluable(typePeriodeEquiv)) {
- return []
- }
- } else {
- return []
- }
- }
-
- // Get evaluations
- List<Evaluation> evaluations = Evaluation.createCriteria().listDistinct {
- eq('enseignement', enseignement)
- periodes {
- or {
- eq('typePeriode', typePeriode)
- if (typePeriodeEquiv) {
- eq('typePeriode', typePeriodeEquiv)
- }
- }
- }
- and {
- order('dateEvaluation', 'asc')
- order('dateCreation', 'asc')
- }
- fetchMode('notes', FetchMode.JOIN)
- fetchMode('modaliteMatiere', FetchMode.JOIN)
- }
-
- // Si l'évaluation est rattachée à un sous-service, on vérifie si le sous-service
- // est évaluable
- List<Evaluation> evaluationsEvaluables = []
- evaluations.each { Evaluation evaluation ->
- if (evaluation.modaliteMatiere == null) {
- evaluationsEvaluables << evaluation
- } else {
- // get sous-services pour cet évaluation
- NotesSousServiceService sousServiceService =
- applicationContext.getBean('notesSousServiceService')
-
- List<TypePeriode> typePeriodes = [typePeriode]
- if (typePeriodeEquiv) {
- typePeriodes << typePeriodeEquiv
- }
-
- List<SousService> sousServices = sousServiceService.
- internalFindAllSousServices(securiteSession,
- service,
- evaluation.modaliteMatiere,
- typePeriodes)
-
- // l'évaluabilité devrait être pareille pour tout les sous-services
- if (sousServices.any { it.evaluable }) {
- evaluationsEvaluables << evaluation
- }
- }
- }
-
- return evaluationsEvaluables
- }
-
- /**
- * Mis à jour de la moyenne d'évaluation
- * @param evaluation
- * @param moyenne
- * @return évaluation
- * @author msan
- */
- Evaluation internalMAJMoyenne(Evaluation evaluation, BigDecimal moyenne) {
- evaluation.moyenne = moyenne
- try {
- if (!evaluation.save(flush: true)) {
- throw new SauvegardeEchoueException(evaluation)
- }
- } catch (ConstraintViolationException e) {
- throw new SauvegardeEchoueException(evaluation, e)
- }
- return evaluation
- }
-
- /**
- * Crée une évaluation
- * @param securiteSession
- * @param params EvaluationParams
- * @return Evaluation
- * @author bper
- */
- Evaluation creeEvaluation(SecuriteSession securiteSession,
- EvaluationParams params)
- throws PeriodeVerrouilleException, NoteMaxNonValideException {
-
- if (params.typePeriode.isAnnee()) {
- throw new IllegalArgumentException(
- "Il n'est pas autorisé de créer une évaluation pour la période \"Année\""
- )
- }
-
- if (params.noteMax != null) {
- internalVerifieNoteMax(params.noteMax)
- }
-
- NotesPeriodeService notesPeriodeService =
- (NotesPeriodeService) applicationContext.getBean('notesPeriodeService')
-
- Enseignement enseignement = params.enseignement
-
- notesDroitService.verifieAutorisationByEnseignement(
- securiteSession,
- enseignement,
- ActionEnum.CREATION,
- (NotesFonction.ENSEIGNANT_ASSIMILE + NotesFonction.DIRECTION_ASSIMILE).toList()
- )
-
- // Périodes
- List<Periode> periodes =
- notesPeriodeService.findAllPeriodesByServiceAndTypePeriode(
- securiteSession,
- params.enseignement.service,
- params.typePeriode
- )
-
- // La création de l'évaluation est interdite si au moins une période est verrouillée
- periodes.each {
- if (it.verrouille) {
- throw new PeriodeVerrouilleException(it)
- }
- }
-
- Evaluation evaluation = new Evaluation(
- titre: params.titre,
- dateEvaluation: params.dateEvaluation,
- noteMaxPossible: params.noteMax,
- coefficient: params.coeff,
- publiable: params.publiable,
- periodes: periodes,
- enseignement: enseignement,
- creeParWebservice: params.creeParWebservice
- )
-
- // Modalité de matière
- evaluation.modaliteMatiere = internalGetModaliteMatiereForEvaluation(
- params.enseignement.service,
- params.typePeriode,
- params.modaliteMatiere)
-
- if (!evaluation.save(flush: true) || evaluation.hasErrors()) {
- throw new SauvegardeEchoueException(evaluation)
- }
-
- return evaluation
- }
-
- /**
- * Vérifie que la modalité de matière peut être utilisée pour un service et un type de
- * période. Sinon retourne une autre modalite de matière valide.
- * @param service
- * @param typePeriode
- * @param modaliteMatiere
- * @return ModaliteMatiere valide
- */
- private ModaliteMatiere internalGetModaliteMatiereForEvaluation(Service service,
- TypePeriode typePeriode,
- ModaliteMatiere modaliteMatiere) {
-
- ModaliteMatiere modaliteMatiereValide = null
-
- NotesSousServiceService sousServiceService =
- (NotesSousServiceService) applicationContext.getBean('notesSousServiceService')
-
- // Liste des relations pour le service et le type de période
- Set<SousService> sousServices =
- sousServiceService.findAllSousServiceByServiceAndTypePeriode(
- service,
- typePeriode,
- true
- ) as Set
-
- List<ModaliteMatiere> modaliteMatieres = sousServices.collect {
- it.modaliteMatiere
- }
-
- if (modaliteMatieres) {
- if (modaliteMatiere) {
- modaliteMatiereValide = (ModaliteMatiere) modaliteMatieres.find {
- it.id == modaliteMatiere.id
- }
- }
-
- if (!modaliteMatiereValide) {
- modaliteMatiereValide = modaliteMatieres.first()
- }
- }
-
- return modaliteMatiereValide
- }
-
- /**
- * Modifie une évaluation
- * @param securiteSession
- * @param params EvaluationParams
- * @return Evaluation
- * @author bper
- */
- Evaluation modifieEvaluation(SecuriteSession securiteSession,
- EvaluationParams params)
- throws AutorisationException,
- IllegalArgumentException,
- SauvegardeEchoueException,
- PeriodeVerrouilleException,
- NoteMaxNonValideException {
-
- Evaluation evaluation = params.evaluation
-
- if (evaluation == null) {
- throw new IllegalArgumentException(
- "Le paramètre {params.evaluaion} ne doit etre null"
- )
- }
-
- if (params.noteMax != null && params.noteMax < evaluation.noteMaxSaisie) {
- throw new NoteMaxSurpasseeException(params.noteMax)
- }
-
- if (params.noteMax != null) {
- internalVerifieNoteMax(params.noteMax)
- }
-
- notesDroitService.verifieAutorisationByEnseignement(
- securiteSession,
- evaluation.enseignement,
- ActionEnum.MODIFICATION,
- (NotesFonction.ENSEIGNANT_ASSIMILE + NotesFonction.DIRECTION_ASSIMILE).toList()
- )
-
- // La modififcation de l'évaluation est interdite si au moins une période est verrouillée
- evaluation.periodes.each {
- if (it.verrouille) {
- throw new PeriodeVerrouilleException(it)
- }
- }
-
- // Si l'évolution change sa modalité de matière il faut marquer les moyennes
- // des sous-services correspondantes à l'ancienne et nouvelle modalité
- ModaliteMatiere ancienneModaliteMatiere = null
- if (params.modaliteMatiere != null) {
- ModaliteMatiere nouvelleModaliteMatiere =
- internalGetModaliteMatiereForEvaluation(
- params.evaluation.enseignement.service,
- params.typePeriode,
- params.modaliteMatiere
- )
-
- if (evaluation.modaliteMatiere.id != nouvelleModaliteMatiere.id) {
- ancienneModaliteMatiere = evaluation.modaliteMatiere
- evaluation.modaliteMatiere = nouvelleModaliteMatiere
- }
- }
-
- if (params.titre) {evaluation.titre = params.titre}
-
- Boolean dateChange = false
- if (params.dateEvaluation) {
- dateChange = (evaluation.dateEvaluation != params.dateEvaluation)
- evaluation.dateEvaluation = params.dateEvaluation
- }
-
- Boolean noteMaxChange = false
- if (params.noteMax != null) {
- noteMaxChange = (evaluation.noteMaxPossible != params.noteMax)
- evaluation.noteMaxPossible = params.noteMax
- }
-
- Boolean coeffChange = false
- if (params.coeff != null) {
- coeffChange = (evaluation.coefficient != params.coeff)
- evaluation.coefficient = params.coeff
- }
-
- if (params.publiable != null) {evaluation.publiable = params.publiable}
-
- if (!evaluation.save(flush: true) || evaluation.hasErrors()) {
- throw new SauvegardeEchoueException(evaluation)
- }
-
- // si le coeff de l'évaluation existant a changé - il faut recalculer les moyennes
- if (coeffChange || noteMaxChange || ancienneModaliteMatiere || dateChange) {
- // invalidate les moyennes correspondantes
- uptodateService.marqueDirtyEvaluation(
- securiteSession,
- evaluation,
- ancienneModaliteMatiere
- )
- }
-
- return evaluation
- }
-
- /**
- * Verifie que la note maximale n'est pas negative ou zero.
- * @param noteMax
- * @throws IllegalArgumentException si la noteMax n'est pas valide
- */
- private void internalVerifieNoteMax(BigDecimal noteMax)
- throws NoteMaxNonValideException {
- if (noteMax <= 0) {
- throw new NoteMaxNonValideException(noteMax)
- }
- }
-
- /**
- * Supprime une évaluation et ses notes
- * @param evaluation
- * @param securiteSession
- * @throws AutorisationException
- * @throws SuppresionEchoueException
- * @author bper
- */
- void supprimeEvaluation(SecuriteSession securiteSession,
- Evaluation evaluation)
- throws AutorisationException,
- SuppresionEchoueException,
- IllegalArgumentException {
-
- if (!evaluation) {
- throw new IllegalArgumentException(
- "La paramètre {evaluation} ne doit pas etre null"
- )
- }
-
- // Vérifie autorisation de supprimer évaluation
- notesDroitService.verifieAutorisationByEnseignement(
- securiteSession,
- evaluation.enseignement,
- ActionEnum.SUPPRESSION,
- (NotesFonction.ENSEIGNANT_ASSIMILE + NotesFonction.DIRECTION_ASSIMILE).toList()
- )
-
- Boolean evalHadNotes = internalEvaluationHasNotes(evaluation)
- //List<Periode> evalPeriodes = evalHadNotes ? evaluation.periodes.toList() : null
-
- // Si évaluation avait les notes, il faut recalculer les moyennes
- if (evalHadNotes) {
- uptodateService.marqueDirtyEvaluation(securiteSession, evaluation)
- }
-
- // Supprime évaluation et les notes en cascade
- evaluation.delete(flush: true)
- if (evaluation.hasErrors()) {
- throw new SuppresionEchoueException(evaluation)
- }
-
- }
-
- /**
- * Vérifie si l'évaluation a des notes
- * @param evaluation
- * @return
- * @author bper
- */
- Boolean internalEvaluationHasNotes(Evaluation evaluation) {
-
- Note note = (Note) Note.createCriteria().get {
- eq('evaluation', evaluation)
- maxResults(1)
- }
-
- if (note) {
- return true
- } else {
- return false
- }
- }
-
- /**
- * Evaluations d'une période avec les notes fetchées.
- * @param periode
- * @param seulementMonoperiodeEvals si true, les évaluation qui sont liées
- * seulement à une période sont retournées
- * @return Evaluations d'une période avec les notes fetchées
- * @author msan
- */
- List<Evaluation> internalFindAllEvaluationsByPeriode(Periode periode,
- Boolean seulementMonoperiodeEvals = true) {
- return Evaluation.createCriteria().listDistinct {
- periodes {
- eq('id', periode.id)
- }
- if (seulementMonoperiodeEvals) {
- sizeEq('periodes', 1)
- }
- fetchMode('notes', FetchMode.JOIN)
- }
- }
-
- /**
- * Supprime les évaluation et les notes qui vont avec
- * @param enseignement
- * @author msan
- */
- void internalSupprimeEvaluations(Enseignement enseignement) {
- internalSupprimeEvaluations(
- internalFindAllEvaluationByEnseignement(enseignement)
- )
- }
-
- /**
- * Supprime les évaluation et les notes qui vont avec
- * @param sousServices liste des sousServices
- * @author msan
- */
- void internalSupprimeEvaluationsBySousServices(List<SousService> sousServices) {
- List<Evaluation> evals = []
- sousServices?.each { SousService sousService ->
- List<Evaluation> evalsSS =
- internalFindAllEvaluationBySousService(sousService)
- if (!evalsSS.isEmpty()) {
- evals.addAll(evalsSS)
- }
- }
- if (evals.size() > 0) {
- internalSupprimeEvaluations(evals)
- }
- }
-
- /**
- * Cherche les évaluations liées à un sous-service
- * @param sousService
- * @return les évaluations liées à un sous-service
- * @author msan
- */
- List<Evaluation> internalFindAllEvaluationBySousService(SousService sousService) {
- return Evaluation.withCriteria {
- eq('modaliteMatiere', sousService.modaliteMatiere)
- enseignement {
- eq('service', sousService.service)
- }
- periodes {
- eq('typePeriode', sousService.typePeriode)
- }
- }
- }
-
- /**
- * Supprime les evaluations et les notes qui vont avec
- * @param evaluations
- * @author msan
- */
- void internalSupprimeEvaluations(List<Evaluation> evaluations) {
- if (evaluations?.size() > 0) {
-
- // supprime les notes
- noteService.internalSupprimeNotes(evaluations)
-
- // supprime les evaluations +
- // enlève relations evaluation - période
- evaluations.each { Evaluation evaluation ->
- // rattache évaluations après le vidage de cache
- if (!evaluation.isAttached()) {
- evaluation = Evaluation.get(evaluation.id)
- }
-
- // on fait le get pour eviter ConcurrentModificationException dans le each suivant
- List<Periode> periodes = evaluation.periodes.collect {
- Periode.get(it.id)
- }
-
- periodes.each { Periode periode ->
- evaluation.removeFromPeriodes(periode)
- }
- }
-
- // N.B. executeUpdate n'arrive pas à prendre une liste comme un paramètre
- // de la requête HQL
- if (evaluations?.size() > 0) {
- notesHibernateSessionService.prepareExecuteUpdate()
- Evaluation.withSession { session ->
- session.createQuery("delete Evaluation e where e in (:evaluations)").
- setParameterList('evaluations', evaluations).executeUpdate()
- }
- }
- }
- }
-
- /**
- * Liste des evaluations d'un enseignement
- * @param ens
- * @return
- */
- List<Evaluation> internalFindAllEvaluationByEnseignement(Enseignement ens) {
- return Evaluation.withCriteria {
- enseignement {
- eq('service', ens.service)
- eq('enseignant', ens.enseignant)
- }
- }
- }
-
- /**
- * Retourne la liste des évaluations pour un enseignement et une liste des périodes
- * @param enseignement
- * @param listePeriodes
- * @return List < Evaluation >
- * @author bper
- */
- List<Evaluation> internalFindAllEvaluationByEnseignementAndPeriode(Enseignement enseignement,
- List<Periode> listePeriodes) {
- return Evaluation.createCriteria().listDistinct {
- eq('enseignement', enseignement)
- periodes {
- 'in'('id', listePeriodes*.id)
- }
- }
- }
-
- /**
- * Total des evaluations pour les enseignements données
- * @param enseignements
- * @return
- * @author msan
- */
- Long internalCompteEvaluationsByEnseignement(List<Enseignement> enseignements) {
- Long evalCount = Evaluation.createCriteria().get {
- 'in'('enseignement', enseignements)
- projections {
- count('id')
- }
- }
-
- return evalCount
- }
-
- /**
- * Cherche s'il y a des évaluations pour les sous-services données
- * @param enseignements
- * @return
- * @author msan
- */
- Boolean internalExistentEvaluationsBySousServices(List<SousService> sousServices) {
- Boolean evalsExistent = false
- for (int i = 0; i < sousServices.size() && !evalsExistent; i++) {
- if (!internalFindAllEvaluationBySousService(sousServices.get(i)).isEmpty()) {
- evalsExistent = true
- }
- }
- return evalsExistent
- }
-
- /**
- * Ajoute la période dans la relation de l'évaluation. Vérifie si la période
- * est rattachée au service de l'évaluation.
- * @param evaluation
- * @param periode
- *
- */
- void internalRattachePeriode(Evaluation evaluation, Periode periode) {
-
- // La période est bloquée
- if (periode.verrouille) {
- return
- }
-
- // L'évoluation a déjà cette periode
- if (evaluation.periodes.find {it.id == periode.id}) {
- return
- }
-
- // Vérifie que la période est rattachée au service
- if (!evaluation.enseignement.service.relPeriodeServices.find {it.periode.id == periode.id}) {
- throw new IllegalArgumentException(
- "La periode [$periode] n'est pas rattachée au service " +
- "[${evaluation.enseignement.service}]"
- )
- }
-
- // Rattache la periode à l'évaluation
- evaluation.addToPeriodes(periode)
- if (!evaluation.save(flush: true)) {
- throw new SauvegardeEchoueException(evaluation)
- }
- }
-
- /**
- * Attache les évaluations du service pour typePeriode donnée à la modalité matière
- * @param service
- * @param modaliteMatiere
- * @param typePeriode
- * @author msan
- */
- void internalRattacheEvaluationsAModaliteMatiere(Service service,
- ModaliteMatiere modaliteMatiere,
- TypePeriode typePeriode) {
- // get evals
- List<Evaluation> evalsABasculer = Evaluation.withCriteria {
- periodes {
- eq('typePeriode', typePeriode)
- }
- enseignement {
- eq('service.id', service.id)
- }
- }
- // attache evals
- if (evalsABasculer?.size() > 0) {
- notesHibernateSessionService.prepareExecuteUpdate()
- Evaluation.withSession { session ->
- session.createQuery("update Evaluation e set modaliteMatiere = :modaliteMatiere where e in (:evaluations)").
- setParameterList('evaluations', evalsABasculer).
- setParameter('modaliteMatiere', modaliteMatiere).
- executeUpdate()
- }
- }
- }
-
- /**
- * Supprime toutes les évaluations
- */
- void internalSupprimeToutes() {
- Evaluation.withSession { session ->
- session.createQuery("delete Evaluation e").executeUpdate()
- }
- }
-
-}
\ No newline at end of file