--- /dev/null
+package org.lilie.services.eliot.applications.absences.bilan
+
+import org.lilie.services.eliot.absences.PreferencesEtablissementAbsences
+import org.lilie.services.eliot.absences.Appel
+import org.lilie.services.eliot.absences.AppelLigne
+import org.lilie.services.eliot.applications.scolarite.calendrier.PlageHoraireService
+import org.lilie.services.eliot.absences.PlageHoraire
+import org.lilie.services.eliot.temps.DateUtil
+import org.lilie.services.eliot.applications.scolarite.horaire.HeureService
+import org.hibernate.SQLQuery
+import org.lilie.services.eliot.requetage.RequetageUtilsService
+
+class BilanPasDecompteService extends RequetageUtilsService{
+
+ PlageHoraireService plageHoraireService
+ HeureService heureService
+
+ protected static final Byte AUCUN = 0
+ protected static final Byte MATIN = 1
+ protected static final Byte APRES_MIDI = 2
+ protected static final Byte MATIN_ET_APRES_MIDI = 3
+
+ /**
+ * Fait le comptage en fonction des données trouvées en base et du paramétrage
+ * @param pref : les préférences de l'établissement
+ * @param appelsDatas : les données de la base
+ * @return un Float
+ */
+ public Float calculeCount(PreferencesEtablissementAbsences pref,
+ List appelsDatas) {
+ switch (pref.pasDecompte) {
+ case PreferencesEtablissementAbsences.DECOMPTE_HEURE:
+ return calculeCountHeure(pref, appelsDatas)
+ case PreferencesEtablissementAbsences.DECOMPTE_DEMIJOUR:
+ return calculeCountDemiJour(
+ appelsDatas,
+ plageHoraireService.getPlageHoraires(pref)
+ )
+ case PreferencesEtablissementAbsences.DECOMPTE_JOUR:
+ return BilanUtils.calculeCountJour(appelsDatas)
+ }
+ }
+
+ /**
+ * Retourne pour chaque appel de la liste, le nombre de demi-journées sur
+ * lesquelles il porte
+ * @param appels : une liste d'appels
+ * @return une map associant à chaque id d'appel, un flag indiquant si l'appel
+ * porte sur le matin, l'après-midi ou les deux
+ */
+ public Map findAllDemiJoursForAllAppels(List<Long> appelIds) {
+ Map result = [:]
+ if (appelIds.size() > 0) {
+ List liste = findAllAppelsWithPlages(appelIds)
+ Boolean matin
+ Boolean apresMidi
+ liste.each {
+ Appel appel ->
+ matin = false
+ apresMidi = false
+ appel.plageHoraires.each {
+ PlageHoraire plage ->
+ if (plage.matin) {
+ matin = true
+ } else {
+ apresMidi = true
+ }
+ }
+ Byte flag = AUCUN
+ if (matin) {
+ flag += MATIN
+ }
+ if (apresMidi) {
+ flag += APRES_MIDI
+ }
+ result.put(appel.id, flag)
+ }
+ }
+ return result
+ }
+
+ /**
+ * Retourne le nombre de demi-journées concernées par un AppelLigne
+ * @param plages : les plages horaires de l'établissement
+ * @return un Byte
+ */
+ public Byte getNbDemiJoursForAppelLigne(AppelLigne appelLigne,
+ List<PlageHoraire> plages) {
+ Date heurePivot = heureService.getHeurePivotFromListPlages(plages)
+ Boolean matin = false
+ Boolean apresMidi = false
+ if (appelLigne.heureDebut < heurePivot) {
+ matin = true
+ }
+ if (appelLigne.heureFin > heurePivot) {
+ apresMidi = true
+ }
+ Byte result = 0
+
+ if (matin) {
+ result++
+ }
+
+ if (apresMidi) {
+ result++
+ }
+
+ return result
+ }
+
+
+ /**
+ * Retourne une map associant à chauqe appel passé en paramètre, le nombre
+ * de plages horaires qu'il concerne
+ * @param appelIds : une List<Long>
+ * @return une map
+ * @author jbui
+ */
+ public Map findPlagesCountForAllAppels(List<Long> appelIds) {
+ List liste = findAllAppelsWithPlages(appelIds)
+ Map result = [:]
+ liste.each {
+ Appel appel ->
+ result.put(appel.id, appel.plageHoraires.size())
+ }
+ return result
+ }
+
+ /**
+ * Retourne le numéro (1 ou 2) de la dernière demi-journée de l'appelLigne
+ * @param plages : plages horaires de l'établissement
+ * @return 1 si l'appel se termine le matin, 2 pour l'après-midi
+ */
+ public Byte getLastDemiJourForAppelLigne(AppelLigne appelLigne,
+ List<PlageHoraire> plages) {
+ Date heurePivot = heureService.getHeurePivotFromListPlages(plages)
+ if (appelLigne.heureFin > heurePivot) {
+ return 2
+ } else {
+ return 1
+ }
+ }
+
+ /**
+ * Retourne les appels de la liste avec leurs plages horaires fetchées
+ * @return une List<Appel>
+ */
+ private List findAllAppelsWithPlages(List<Long> appelIds) {
+ def result = []
+ if (appelIds && appelIds[0]) {
+
+ SQLQuery sqlQuery = prepareRequete(BilanRequetesConstantes.SQL_GET_APPELS)
+
+ sqlQuery.addEntity(Appel)
+
+ sqlQuery.setParameterList(BilanRequetesConstantes.ALL_APPEL, appelIds)
+
+ result = sqlQuery.list()
+ }
+ return result
+ }
+
+ /**
+ * Fait le comptage des absences en heures
+ * @return un Float
+ */
+ private Float calculeCountHeure(PreferencesEtablissementAbsences pref,
+ List appelsDatas) {
+ Set<Long> appelIds = []
+ appelsDatas.each {
+ if (it[1]?.id) {
+ appelIds << it[1].id
+ }
+ }
+ Map nbPlagesParAppel = findPlagesCountForAllAppels(appelIds.toList())
+ Float result = 0.0
+ appelsDatas.each {
+ Appel appel = (Appel) it[1]
+ if (appel) {
+ Integer nbPlages = (Integer) nbPlagesParAppel.getAt(appel.id)
+ result += (nbPlages * pref.longueurPlage)
+ } else {
+ Integer nbPlages = BilanUtils.calculeNbPlagesForAppelLigne(
+ plageHoraireService.getPlageHoraires(pref),
+ (AppelLigne) it[0]
+ )
+ result += (nbPlages * pref.longueurPlage)
+ }
+ }
+ return result
+ }
+
+ /**
+ * Fait le comptage des absences en demi-journées
+ * @return un Float
+ */
+ private Float calculeCountDemiJour(List appelsDatas, List<PlageHoraire> plages) {
+ Set<Long> appelIds = []
+ appelsDatas.each {
+ if (it[1]?.id) {
+ appelIds << it[1].id
+ }
+ }
+ Map demiJoursParAppel = findAllDemiJoursForAllAppels(appelIds.toList())
+
+ Calendar cal = Calendar.getInstance()
+ Float result = 0.0
+ Date currentJour
+ Byte currentDemiJour
+ Date lastJour
+ Byte lastDemiJour
+
+ appelsDatas.sort {
+ def data1, def data2 ->
+ BilanUtils.getDateDebut(data1) <=> BilanUtils.getDateDebut(data2)
+ }.each {
+ Appel appel = (Appel) it[1]
+ AppelLigne appelLigne = (AppelLigne) it[0]
+ Byte demiJours
+ Byte nbDemiJours
+
+ if (appel) {
+ demiJours = (Byte) demiJoursParAppel.getAt(appel.id)
+ nbDemiJours = 1
+ if (demiJours == MATIN_ET_APRES_MIDI) {
+ nbDemiJours = 2
+ }
+ cal.setTime(appel.dateHeureDebut)
+ } else {
+ nbDemiJours = getNbDemiJoursForAppelLigne(appelLigne, plages)
+ demiJours = getLastDemiJourForAppelLigne(appelLigne, plages)
+ cal.setTime(appelLigne.absenceJournee.date)
+ }
+
+ DateUtil.setDebutJour(cal)
+ currentJour = cal.getTime()
+ cal.clear()
+ currentDemiJour = demiJours
+ if (currentDemiJour == MATIN_ET_APRES_MIDI) {
+ currentDemiJour = APRES_MIDI
+ } else {
+ if (currentDemiJour == AUCUN) {
+ throw new IllegalStateException(
+ "L'appel ne porte ni sur le matin, ni sur l'après-midi."
+ )
+ }
+ }
+ if ((lastJour != currentJour) || (lastDemiJour != currentDemiJour)) {
+ result += nbDemiJours
+ }
+ lastDemiJour = currentDemiJour
+ lastJour = currentJour
+ }
+ return result
+ }
+
+}
--- /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.applications.absences.bilan
+
+class BilanRequetesConstantes {
+
+ public final static String ALL_APPEL = 'allAppel'
+
+ public static final String HQL_DE_BASE = """
+ select al, appel
+ from AppelLigne al
+ left join al.appel appel
+ left join appel.preferencesEtablissementAbsences pref
+ left join pref.etablissement etab
+ left join al.absenceJournee aj
+ left join aj.etablissement etab2
+ inner join al.autorite autorite
+ where al.autorite.id = :eleveId
+ and (
+ (
+ appel.id is not null
+ and etab.id = :etabCourantId
+ and appel.dateHeureDebut < :dateFin
+ and appel.dateHeureFin > :dateDebut
+ ) or (
+ aj.id is not null
+ and etab2.id = :etabCourantId
+ and (aj.date + al.heureDebut) < :dateFin
+ and (aj.date + al.heureFin) > :dateDebut
+ )
+ )
+ and al.absencePrevisionnelle = false
+ """
+
+ // juste un fetch en plus par rapport à HQL_DE_BASE
+ public static final String HQL_DE_BASE_FETCH_ABSENCE_JOURNEE = """
+ select al, appel
+ from AppelLigne al
+ left join al.appel appel
+ left join appel.preferencesEtablissementAbsences pref
+ left join pref.etablissement etab
+ left join fetch al.absenceJournee aj
+ left join aj.etablissement etab2
+ inner join al.autorite autorite
+ where al.autorite.id = :eleveId
+ and (
+ (
+ appel.id is not null
+ and etab.id = :etabCourantId
+ and appel.dateHeureDebut < :dateFin
+ and appel.dateHeureFin > :dateDebut
+ ) or (
+ aj.id is not null
+ and etab2.id = :etabCourantId
+ and (aj.date + al.heureDebut) < :dateFin
+ and (aj.date + al.heureFin) > :dateDebut
+ )
+ )
+ and al.absencePrevisionnelle = false
+ """
+
+ public static final String ORDER_BY = " order by appel.dateHeureDebut, aj.date, al.heureDebut"
+
+ public static final String HQL_ABSENCES_RETARDS = """
+ select distinct al, personne, a.id
+ from AppelLigne al
+ left join fetch al.appel appel
+ left join appel.preferencesEtablissementAbsences pref
+ left join pref.etablissement etab
+ left join fetch al.absenceJournee aj
+ left join aj.etablissement etab2
+ inner join al.autorite a,
+ Personne personne
+
+ where a.id in (:elevesIds)
+ and personne.autorite = a
+ and (
+ (
+ appel is not null
+ and etab.id = :etabCourantId
+ and appel.dateHeureFin <= :dateFin
+ and appel.dateHeureDebut >= :dateDebut
+ )
+ or
+ (
+ aj is not null
+ and etab2.id = :etabCourantId
+ and aj.date >= :dateDebut
+ and aj.date <= :dateFin
+ )
+ )
+ """
+
+
+ public static final String SQL_GET_APPELS = """
+ WITH allAppel AS (
+ (SELECT unnest(array[:allAppel]) AS id)
+ )
+
+ SELECT ap.* FROM enttemps.appel ap
+ INNER JOIN enttemps.appel_plage_horaire aph ON ap.id = aph.appel_id
+ INNER JOIN enttemps.plage_horaire ph ON aph.plage_horaire_id = ph.id
+ INNER JOIN allAppel aa ON ap.id = aa.id
+ GROUP BY ap.id;
+ """
+
+}
import org.lilie.services.eliot.absences.Motif
import org.lilie.services.eliot.securite.Autorite
import org.lilie.services.eliot.absences.statistiques.commons.StatsAbsencesParPeriode
-
-import org.hibernate.Session
-import org.hibernate.SessionFactory
-import org.hibernate.SQLQuery
import org.lilie.services.eliot.scolarite.structureenseignement.LocalStructureEnseignementServiceHql
import org.lilie.services.eliot.applications.absences.PriseEnCompteMotif
import org.lilie.services.eliot.applications.absences.BasicCriteresRecherche
import org.lilie.services.eliot.applications.absences.StatAbsences
import org.lilie.services.eliot.applications.absences.AutoritePublipostageService
import org.lilie.services.eliot.scolarite.structureenseignement.LocalClasseService
-import org.lilie.services.eliot.applications.scolarite.horaire.HeureService
class BilanService {
static transactional = true
+
CalendrierService calendrierService
LocalStructureEnseignementService localStructureEnseignementService
LocalPersonneService localPersonneService
PlageHoraireService plageHoraireService
AutoritePublipostageService autoritePublipostageService
LocalClasseService localClasseService
-
- SessionFactory sessionFactory
+ BilanPasDecompteService bilanPasDecompteService
public static final String ABSENCES_EXCUSEES_NB = 'excuseesNb'
public static final String ABSENCES_NON_EXCUSEES_NB = 'nonExcuseesNb'
public static final String ABSENCES_INTERNAT = 'absencesInternat'
public static final String DEPARTS_ANTICIPES = 'departsAnticipes'
-
protected static final Byte AUCUN = 0
protected static final Byte MATIN = 1
protected static final Byte APRES_MIDI = 2
protected static final Byte MATIN_ET_APRES_MIDI = 3
- private final static String ALL_APPEL = 'allAppel'
-
- private static final String HQL_DE_BASE = """
- select al, appel
- from AppelLigne al
- left join al.appel appel
- left join appel.preferencesEtablissementAbsences pref
- left join pref.etablissement etab
- left join al.absenceJournee aj
- left join aj.etablissement etab2
- inner join al.autorite autorite
- where al.autorite.id = :eleveId
- and (
- (
- appel.id is not null
- and etab.id = :etabCourantId
- and appel.dateHeureDebut < :dateFin
- and appel.dateHeureFin > :dateDebut
- ) or (
- aj.id is not null
- and etab2.id = :etabCourantId
- and (aj.date + al.heureDebut) < :dateFin
- and (aj.date + al.heureFin) > :dateDebut
- )
- )
- and al.absencePrevisionnelle = false
- """
-
- // juste un fetch en plus par rapport à HQL_DE_BASE
- private static final String HQL_DE_BASE_FETCH_ABSENCE_JOURNEE = """
- select al, appel
- from AppelLigne al
- left join al.appel appel
- left join appel.preferencesEtablissementAbsences pref
- left join pref.etablissement etab
- left join fetch al.absenceJournee aj
- left join aj.etablissement etab2
- inner join al.autorite autorite
- where al.autorite.id = :eleveId
- and (
- (
- appel.id is not null
- and etab.id = :etabCourantId
- and appel.dateHeureDebut < :dateFin
- and appel.dateHeureFin > :dateDebut
- ) or (
- aj.id is not null
- and etab2.id = :etabCourantId
- and (aj.date + al.heureDebut) < :dateFin
- and (aj.date + al.heureFin) > :dateDebut
- )
- )
- and al.absencePrevisionnelle = false
- """
-
- private static final String ORDER_BY = " order by appel.dateHeureDebut, aj.date, al.heureDebut"
-
-
- private static final String HQL_ABSENCES_RETARDS = """
- select distinct al, personne, a.id
- from AppelLigne al
- left join fetch al.appel appel
- left join appel.preferencesEtablissementAbsences pref
- left join pref.etablissement etab
- left join fetch al.absenceJournee aj
- left join aj.etablissement etab2
- inner join al.autorite a,
- Personne personne
-
- where a.id in (:elevesIds)
- and personne.autorite = a
- and (
- (
- appel is not null
- and etab.id = :etabCourantId
- and appel.dateHeureFin <= :dateFin
- and appel.dateHeureDebut >= :dateDebut
- )
- or
- (
- aj is not null
- and etab2.id = :etabCourantId
- and aj.date >= :dateDebut
- and aj.date <= :dateFin
- )
- )
- """
-
-
- private static final String SQL_GET_APPELS = """
- WITH allAppel AS (
- (SELECT unnest(array[:allAppel]) AS id)
- )
-
- SELECT ap.* FROM enttemps.appel ap
- INNER JOIN enttemps.appel_plage_horaire aph ON ap.id = aph.appel_id
- INNER JOIN enttemps.plage_horaire ph ON aph.plage_horaire_id = ph.id
- INNER JOIN allAppel aa ON ap.id = aa.id
- GROUP BY ap.id;
- """
-
/**
* Calcule le bilan des absences de l'élève sur la période
* @param eleve : autorité de l'élève
* PreferencesEtablissementAbsences.DECOMPTE_DEMIJOUR
* PreferencesEtablissementAbsences.DECOMPTE_JOUR
*/
- Map calculeBilanForEleveAndPeriode(
+ public Map calculeBilanForEleveAndPeriode(
SecuriteSession securiteSession,
Autorite eleve,
Date dateDebut,
return result
}
- /**
- * Retourne une map associant à chauqe appel passé en paramètre, le nombre
- * de plages horaires qu'il concerne
- * @param appelIds : une List<Long>
- * @return une map
- * @author jbui
- */
- Map findPlagesCountForAllAppels(List<Long> appelIds) {
- List liste = findAllAppelsWithPlages(appelIds)
- Map result = [:]
- liste.each {
- Appel appel ->
- result.put(appel.id, appel.plageHoraires.size())
- }
- return result
- }
-
- /**
- * Retourne pour chaque appel de la liste, le nombre de demi-journées sur
- * lesquelles il porte
- * @param appels : une liste d'appels
- * @return une map associant à chaque id d'appel, un flag indiquant si l'appel
- * porte sur le matin, l'après-midi ou les deux
- */
- public Map findAllDemiJoursForAllAppels(List<Long> appelIds) {
- Map result = [:]
- if (appelIds.size() > 0) {
- List liste = findAllAppelsWithPlages(appelIds)
- Boolean matin
- Boolean apresMidi
- liste.each {
- Appel appel ->
- matin = false
- apresMidi = false
- appel.plageHoraires.each {
- PlageHoraire plage ->
- if (plage.matin) {
- matin = true
- } else {
- apresMidi = true
- }
- }
- Byte flag = AUCUN
- if (matin) {
- flag += MATIN
- }
- if (apresMidi) {
- flag += APRES_MIDI
- }
- result.put(appel.id, flag)
- }
- }
- return result
- }
-
- /**
- * Retourne les appels de la liste avec leurs plages horaires fetchées
- * @return une List<Appel>
- */
- private List findAllAppelsWithPlages(List<Long> appelIds) {
- def result = []
- if (appelIds && appelIds[0]) {
- Session session = sessionFactory.getCurrentSession()
-
- SQLQuery sqlQuery = session.createSQLQuery(SQL_GET_APPELS)
-
- sqlQuery.addEntity(Appel)
-
- sqlQuery.setParameterList(ALL_APPEL, appelIds)
-
- result = sqlQuery.list()
- }
- return result
- }
-
/**
* Calcule le nombre de retards pour l'élève sur la période
* @param pref : les préférences de l'établissement
Date dateFin,
PriseEnCompteMotif priseEnCompteMotif
) {
- String hql = HQL_DE_BASE + """
+ String hql = BilanRequetesConstantes.HQL_DE_BASE + """
and al.retard = true
and al.presence = true
"""
- hql += getRestrictionForPriseEnCompteMotifs(priseEnCompteMotif)
+ hql += BilanUtils.getRestrictionForPriseEnCompteMotifs(priseEnCompteMotif)
- hql += ORDER_BY
+ hql += BilanRequetesConstantes.ORDER_BY
return AppelLigne.executeQuery(hql, [
eleveId: eleve.autoriteId,
])
}
- /**
- * @return la restriction HQL pour tenir compte de la prise en compte des
- * motifs dans les bulletins ou les stats
- */
- private String getRestrictionForPriseEnCompteMotifs(
- PriseEnCompteMotif priseEnCompteMotif
- ) {
- switch (priseEnCompteMotif) {
- case PriseEnCompteMotif.BULLETIN:
- return "and al.motif.dispoBulletin = true"
-
- case PriseEnCompteMotif.STATS:
- return "and al.motif.dispoStats = true"
- }
- return ""
- }
-
/**
* Calcule le noombre d'absences non excusées pour un élève et une période
* @param pref : les préférences de l'établissement
dateFin,
priseEnCompteMotif
)
- return calculeCount(pref, appelsDatas)
+ return bilanPasDecompteService.calculeCount(pref, appelsDatas)
}
/**
Date dateDebut,
Date dateFin,
PriseEnCompteMotif priseEnCompteMotif) {
- String hql = HQL_DE_BASE_FETCH_ABSENCE_JOURNEE + """
+ String hql = BilanRequetesConstantes.HQL_DE_BASE_FETCH_ABSENCE_JOURNEE + """
and al.presence = false
and al.motif.modifiable = false
"""
- hql += getRestrictionForPriseEnCompteMotifs(priseEnCompteMotif)
+ hql += BilanUtils.getRestrictionForPriseEnCompteMotifs(priseEnCompteMotif)
- hql += ORDER_BY
+ hql += BilanRequetesConstantes.ORDER_BY
return AppelLigne.executeQuery(hql, [
eleveId: eleve.autoriteId,
dateFin: DateUtil.setFinJour(dateFin),
DateUtil.setFinJour(dateFin),
priseEnCompteMotif
)
- return calculeCount(pref, appelsDatas)
+ return bilanPasDecompteService.calculeCount(pref, appelsDatas)
}
private List findAbsencesExcuseesForEleveAndPeriode(
Date dateDebut,
Date dateFin,
PriseEnCompteMotif priseEnCompteMotif) {
- String hql = HQL_DE_BASE_FETCH_ABSENCE_JOURNEE + """
+ String hql = BilanRequetesConstantes.HQL_DE_BASE_FETCH_ABSENCE_JOURNEE + """
and al.presence = false
and al.motif.modifiable = true
"""
- hql += getRestrictionForPriseEnCompteMotifs(priseEnCompteMotif)
+ hql += BilanUtils.getRestrictionForPriseEnCompteMotifs(priseEnCompteMotif)
- hql += ORDER_BY
+ hql += BilanRequetesConstantes.ORDER_BY
return AppelLigne.executeQuery(hql, [
eleveId: eleve.autoriteId,
dateFin: DateUtil.setFinJour(dateFin),
])
}
- /**
- * Fait le comptage en fonction des données trouvées en base et du paramétrage
- * @param pref : les préférences de l'établissement
- * @param appelsDatas : les données de la base
- * @return un Float
- */
- private Float calculeCount(PreferencesEtablissementAbsences pref,
- List appelsDatas) {
- switch (pref.pasDecompte) {
- case PreferencesEtablissementAbsences.DECOMPTE_HEURE:
- return calculeCountHeure(pref, appelsDatas)
- case PreferencesEtablissementAbsences.DECOMPTE_DEMIJOUR:
- return calculeCountDemiJour(
- appelsDatas,
- plageHoraireService.getPlageHoraires(pref)
- )
- case PreferencesEtablissementAbsences.DECOMPTE_JOUR:
- return calculeCountJour(appelsDatas)
- }
- }
-
- /**
- * Fait le comptage des absences en jours
- * @return un Float
- */
- private Float calculeCountJour(List appelsDatas) {
- Date lastDay = null
- Date currentDay = null
- Float result = 0.0
- Calendar cal = Calendar.getInstance()
- appelsDatas.sort {
- def data1, def data2 ->
- getDateDebut(data1) <=> getDateDebut(data2)
- }.each {
- Appel appel = (Appel) it[1]
- cal.clear()
- if (appel) {
- cal.setTime(appel.dateHeureDebut)
- } else {
- AbsenceJournee absenceJournee = ((AppelLigne) it[0]).absenceJournee
- cal.setTime(absenceJournee.date)
- }
- DateUtil.setDebutJour(cal)
- currentDay = cal.getTime()
- if (cal.getTime() != lastDay) {
- result += 1
- }
- lastDay = currentDay
- }
- return result
- }
-
- /**
- * Fait le comptage des absences en demi-journées
- * @return un Float
- */
- private Float calculeCountDemiJour(List appelsDatas, List<PlageHoraire> plages) {
- Set<Long> appelIds = []
- appelsDatas.each {
- if (it[1]?.id) {
- appelIds << it[1].id
- }
- }
- Map demiJoursParAppel = findAllDemiJoursForAllAppels(appelIds.toList())
-
- Calendar cal = Calendar.getInstance()
- Float result = 0.0
- Date currentJour
- Byte currentDemiJour
- Date lastJour
- Byte lastDemiJour
-
- appelsDatas.sort {
- def data1, def data2 ->
- getDateDebut(data1) <=> getDateDebut(data2)
- }.each {
- Appel appel = (Appel) it[1]
- AppelLigne appelLigne = (AppelLigne) it[0]
- Byte demiJours
- Byte nbDemiJours
-
- if (appel) {
- demiJours = (Byte) demiJoursParAppel.getAt(appel.id)
- nbDemiJours = 1
- if (demiJours == MATIN_ET_APRES_MIDI) {
- nbDemiJours = 2
- }
- cal.setTime(appel.dateHeureDebut)
- } else {
- nbDemiJours = getNbDemiJoursForAppelLigne(appelLigne, plages)
- demiJours = getLastDemiJourForAppelLigne(appelLigne, plages)
- cal.setTime(appelLigne.absenceJournee.date)
- }
-
- DateUtil.setDebutJour(cal)
- currentJour = cal.getTime()
- cal.clear()
- currentDemiJour = demiJours
- if (currentDemiJour == MATIN_ET_APRES_MIDI) {
- currentDemiJour = APRES_MIDI
- } else {
- if (currentDemiJour == AUCUN) {
- throw new IllegalStateException(
- "L'appel ne porte ni sur le matin, ni sur l'après-midi."
- )
- }
- }
- if ((lastJour != currentJour) || (lastDemiJour != currentDemiJour)) {
- result += nbDemiJours
- }
- lastDemiJour = currentDemiJour
- lastJour = currentJour
- }
- return result
- }
-
- /**
- * Retourne la date et heure de début d'une ligne de data
- */
- private Date getDateDebut(def data) {
- Appel appel = (Appel) data[1]
- AppelLigne appelLigne = (AppelLigne) data[0]
- if (appel) {
- return appel.dateHeureDebut
- } else {
- return DateUtil.calculeDateHeureForDateEtHeure(
- appelLigne.absenceJournee.date,
- appelLigne.heureDebut
- )
- }
- }
-
- /**
- * Fait le comptage des absences en heures
- * @return un Float
- */
- private Float calculeCountHeure(PreferencesEtablissementAbsences pref,
- List appelsDatas) {
- Set<Long> appelIds = []
- appelsDatas.each {
- if (it[1]?.id) {
- appelIds << it[1].id
- }
- }
- Map nbPlagesParAppel = findPlagesCountForAllAppels(appelIds.toList())
- Float result = 0.0
- appelsDatas.each {
- Appel appel = (Appel) it[1]
- if (appel) {
- Integer nbPlages = (Integer) nbPlagesParAppel.getAt(appel.id)
- result += (nbPlages * pref.longueurPlage)
- } else {
- Integer nbPlages = calculeNbPlagesForAppelLigne(
- plageHoraireService.getPlageHoraires(pref),
- (AppelLigne) it[0]
- )
- result += (nbPlages * pref.longueurPlage)
- }
- }
- return result
- }
-
- HeureService heureService
-
- /**
- * Retourne le numéro (1 ou 2) de la dernière demi-journée de l'appelLigne
- * @param plages : plages horaires de l'établissement
- * @return 1 si l'appel se termine le matin, 2 pour l'après-midi
- */
- protected Byte getLastDemiJourForAppelLigne(AppelLigne appelLigne,
- List<PlageHoraire> plages) {
- Date heurePivot = heureService.getHeurePivotFromListPlages(plages)
- if (appelLigne.heureFin > heurePivot) {
- return 2
- } else {
- return 1
- }
- }
-
- /**
- * Retourne le nombre de demi-journées concernées par un AppelLigne
- * @param plages : les plages horaires de l'établissement
- * @return un Byte
- */
- protected Byte getNbDemiJoursForAppelLigne(AppelLigne appelLigne,
- List<PlageHoraire> plages) {
- Date heurePivot = heureService.getHeurePivotFromListPlages(plages)
- Boolean matin = false
- Boolean apresMidi = false
- if (appelLigne.heureDebut < heurePivot) {
- matin = true
- }
- if (appelLigne.heureFin > heurePivot) {
- apresMidi = true
- }
- Byte result = 0
- if (matin) { result++ }
- if (apresMidi) { result++ }
- return result
- }
-
- /**
- * Calcule le nombre de plages horaires sur lesquelles porte l'absence
- * @param plages : la liste des plages horaires de l'établissement
- * @param appelLigne : la ligne d'absence
- * @return un Integer
- */
- protected Integer calculeNbPlagesForAppelLigne(List<PlageHoraire> plages,
- AppelLigne appelLigne) {
- Integer count = 0
- plages.each {
- if (appelLigne.heureFin > it.debut && appelLigne.heureDebut < it.fin) {
- count++
- }
- }
- return count
- }
-
/**
* Contruit et exécute la requête de sélection des lignes d'appel
* @param criteres : les critères de sélection
// facteur multiplicatif : x 2 si 1 changement, x 3 si 2 changements...
- String hql = HQL_ABSENCES_RETARDS
+ String hql = BilanRequetesConstantes.HQL_ABSENCES_RETARDS
if (!criteres.motifIds.contains(BasicCriteresRecherche.VALEUR_TOUS)) {
hql += "and al.motif.id in (:motifIds)"
List<PlageHoraire> plages) {
Float count = 0.0
Set<Appel> appels = datas.appels
- Map nbPlagesParAppel = findPlagesCountForAllAppels(appels*.id)
+ Map nbPlagesParAppel = bilanPasDecompteService.findPlagesCountForAllAppels(appels*.id)
Map result = [:]
datas.eachAbsence { Personne personne, BilanAbsenceInfo bilanAbsenceInfo ->
if (appel) {
nbPlages = (Integer) nbPlagesParAppel.getAt(appel.id)
} else {
- nbPlages = calculeNbPlagesForAppelLigne(plages, appelLigne)
+ nbPlages = BilanUtils.calculeNbPlagesForAppelLigne(plages, appelLigne)
}
count = result.get(eleve) ?: 0
count += (Float) nbPlages * pref.longueurPlage
private Map calculeNbAbsencesParEleveEnDemiJours(BilanAbsencesParPersonneInfo datas,
List<PlageHoraire> plages) {
Set<Appel> appels = datas.appels
- Map demiJoursParAppel = findAllDemiJoursForAllAppels(appels*.id)
+ Map demiJoursParAppel = bilanPasDecompteService.findAllDemiJoursForAllAppels(appels*.id)
Map result = [:]
Calendar cal = Calendar.getInstance()
nbDemiJours = 2
}
} else {
- nbDemiJours = getNbDemiJoursForAppelLigne(appelLigne, plages)
- demiJours = getLastDemiJourForAppelLigne(appelLigne, plages)
+ nbDemiJours = bilanPasDecompteService.getNbDemiJoursForAppelLigne(appelLigne, plages)
+ demiJours = bilanPasDecompteService.getLastDemiJourForAppelLigne(appelLigne, plages)
cal.setTime(appelLigne.absenceJournee.date)
}
List<PlageHoraire> plages,
StatsAbsencesParPeriode stats) {
Set<Long> appelIds = absencesDatas.appels*.id
- Map nbPlagesParAppel = findPlagesCountForAllAppels(appelIds.toList())
+ Map nbPlagesParAppel = bilanPasDecompteService.findPlagesCountForAllAppels(appelIds.toList())
Calendar cal = Calendar.getInstance()
nbPlages = (Integer) nbPlagesParAppel[appel.id]
} else {
dateAbsence = absenceJournee.date
- nbPlages = calculeNbPlagesForAppelLigne(plages, appelLigne)
+ nbPlages = BilanUtils.calculeNbPlagesForAppelLigne(plages, appelLigne)
}
def multiplicateur
return stats
}
- public StatsAbsencesParPeriode calculeCountAbsencesRetardDepart(BilanAbsencesParPersonneInfo absencesDatas,
- PreferencesEtablissementAbsences pref,
- StatsAbsencesParPeriode stats) {
-
- absencesDatas.eachAbsence {
- Personne personne, BilanAbsenceInfo info ->
- Appel appel = info.appelLigne.appel
- AbsenceJournee absenceJournee = info.absenceJournee
- StructureEnseignement struct = info.structureEnseignement
- Date dateAbsence
-
- if (appel) {
- dateAbsence = appel.dateHeureDebut
- } else {
- dateAbsence = absenceJournee.date
- }
-
- stats.incrementeValeur(struct, personne, dateAbsence, 1)
- }
- return stats
- }
-
/**
* Calcule le nombre d'absences en demi-journées
* @param absencesDatas : les données d'absences
StatsAbsencesParPeriode stats) {
Set<Appel> appels = absencesDatas.appels
- Map demiJoursParAppel = findAllDemiJoursForAllAppels(appels*.id)
+ Map demiJoursParAppel = bilanPasDecompteService.findAllDemiJoursForAllAppels(appels*.id)
List<PlageHoraire> plages = plageHoraireService.getPlageHoraires(pref)
Long lastEleveId = null
dateAbsence = appel.dateHeureDebut
cal.setTime(appel.dateHeureDebut)
} else {
- nbDemiJours = getNbDemiJoursForAppelLigne(appelLigne, plages)
- demiJours = getLastDemiJourForAppelLigne(appelLigne, plages)
+ nbDemiJours = bilanPasDecompteService.getNbDemiJoursForAppelLigne(appelLigne, plages)
+ demiJours = bilanPasDecompteService.getLastDemiJourForAppelLigne(appelLigne, plages)
cal.setTime(appelLigne.absenceJournee.date)
dateAbsence = appelLigne.absenceJournee.date
}
currentJour != lastJour ||
currentDemiJour != lastDemiJour) {
- Double valeur = getIncrementValeur(
+ Double valeur = BilanUtils.getIncrementValeur(
nbDemiJours,
lastDemiJour,
currentJour,
return stats
}
- private Double getIncrementValeur(Byte nbDemiJours,
- Byte lastDemiJour,
- Date currentJour,
- Date lastJour) {
- /**
- * Pour une absence qui s'étale sur 2 1/2 journées (matin et après-midi),
- * on vérifie que l'absence précédente ne date pas du matin même,
- * auquel cas, la nouvelle absence ne compte que pour l'après-midi
- */
- if (nbDemiJours == 2) {
- if (currentJour == lastJour && lastDemiJour == BilanService.MATIN) {
- return 1
- } else {
- return 2
- }
- } else {
- return nbDemiJours
- }
- }
-
/**
* Calcule le nombre d'absences en journées
* @param absencesDatas : les données d'absences
--- /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.applications.absences.bilan
+
+import org.lilie.services.eliot.absences.statistiques.commons.StatsAbsencesParPeriode
+import org.lilie.services.eliot.absences.PreferencesEtablissementAbsences
+import org.lilie.services.eliot.scolarite.Personne
+import org.lilie.services.eliot.absences.Appel
+import org.lilie.services.eliot.absences.AbsenceJournee
+import org.lilie.services.eliot.scolarite.StructureEnseignement
+import org.lilie.services.eliot.applications.absences.PriseEnCompteMotif
+import org.lilie.services.eliot.absences.AppelLigne
+import org.lilie.services.eliot.temps.DateUtil
+import org.lilie.services.eliot.absences.PlageHoraire
+
+/**
+ * classe utilitaire pour bilanService
+ */
+class BilanUtils {
+
+ public static Double getIncrementValeur(Byte nbDemiJours,
+ Byte lastDemiJour,
+ Date currentJour,
+ Date lastJour) {
+ /**
+ * Pour une absence qui s'étale sur 2 1/2 journées (matin et après-midi),
+ * on vérifie que l'absence précédente ne date pas du matin même,
+ * auquel cas, la nouvelle absence ne compte que pour l'après-midi
+ */
+ if (nbDemiJours == 2) {
+ if (currentJour == lastJour && lastDemiJour == BilanService.MATIN) {
+ return 1
+ } else {
+ return 2
+ }
+ } else {
+ return nbDemiJours
+ }
+ }
+
+ public static StatsAbsencesParPeriode calculeCountAbsencesRetardDepart(BilanAbsencesParPersonneInfo absencesDatas,
+ PreferencesEtablissementAbsences pref,
+ StatsAbsencesParPeriode stats) {
+
+ absencesDatas.eachAbsence {
+ Personne personne, BilanAbsenceInfo info ->
+ Appel appel = info.appelLigne.appel
+ AbsenceJournee absenceJournee = info.absenceJournee
+ StructureEnseignement struct = info.structureEnseignement
+ Date dateAbsence
+
+ if (appel) {
+ dateAbsence = appel.dateHeureDebut
+ } else {
+ dateAbsence = absenceJournee.date
+ }
+
+ stats.incrementeValeur(struct, personne, dateAbsence, 1)
+ }
+ return stats
+ }
+
+ /**
+ * @return la restriction HQL pour tenir compte de la prise en compte des
+ * motifs dans les bulletins ou les stats
+ */
+ public static String getRestrictionForPriseEnCompteMotifs(
+ PriseEnCompteMotif priseEnCompteMotif
+ ) {
+ switch (priseEnCompteMotif) {
+ case PriseEnCompteMotif.BULLETIN:
+ return "and al.motif.dispoBulletin = true"
+
+ case PriseEnCompteMotif.STATS:
+ return "and al.motif.dispoStats = true"
+ }
+ return ""
+ }
+
+ /**
+ * Fait le comptage des absences en jours
+ * @return un Float
+ */
+ public static Float calculeCountJour(List appelsDatas) {
+ Date lastDay = null
+ Date currentDay = null
+ Float result = 0.0
+ Calendar cal = Calendar.getInstance()
+ appelsDatas.sort {
+ def data1, def data2 ->
+ getDateDebut(data1) <=> getDateDebut(data2)
+ }.each {
+ Appel appel = (Appel) it[1]
+ cal.clear()
+ if (appel) {
+ cal.setTime(appel.dateHeureDebut)
+ } else {
+ AbsenceJournee absenceJournee = ((AppelLigne) it[0]).absenceJournee
+ cal.setTime(absenceJournee.date)
+ }
+ DateUtil.setDebutJour(cal)
+ currentDay = cal.getTime()
+ if (cal.getTime() != lastDay) {
+ result += 1
+ }
+ lastDay = currentDay
+ }
+ return result
+ }
+
+ /**
+ * Retourne la date et heure de début d'une ligne de data
+ */
+ public static Date getDateDebut(def data) {
+ Appel appel = (Appel) data[1]
+ AppelLigne appelLigne = (AppelLigne) data[0]
+ if (appel) {
+ return appel.dateHeureDebut
+ } else {
+ return DateUtil.calculeDateHeureForDateEtHeure(
+ appelLigne.absenceJournee.date,
+ appelLigne.heureDebut
+ )
+ }
+ }
+
+ /**
+ * Calcule le nombre de plages horaires sur lesquelles porte l'absence
+ * @param plages : la liste des plages horaires de l'établissement
+ * @param appelLigne : la ligne d'absence
+ * @return un Integer
+ */
+ public static Integer calculeNbPlagesForAppelLigne(List<PlageHoraire> plages,
+ AppelLigne appelLigne) {
+ Integer count = 0
+ plages.each {
+ if (appelLigne.heureFin > it.debut && appelLigne.heureDebut < it.fin) {
+ count++
+ }
+ }
+ return count
+ }
+
+
+}