forked from ScoDoc/ScoDoc
446 lines
16 KiB
Python
446 lines
16 KiB
Python
# -*- mode: python -*-
|
|
# -*- coding: utf-8 -*-
|
|
|
|
##############################################################################
|
|
#
|
|
# Gestion scolarite IUT
|
|
#
|
|
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program 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
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
|
#
|
|
##############################################################################
|
|
|
|
"""Feuille excel pour préparation des jurys classiques (non BUT)
|
|
"""
|
|
import time
|
|
|
|
from flask import abort
|
|
|
|
from app.but import jury_but
|
|
from app.but.cursus_but import EtudCursusBUT
|
|
from app.but.prepajury_desc import ParcoursDesc, FormsemestreDesc
|
|
from app.models import (
|
|
FormSemestre,
|
|
ApcParcours,
|
|
Formation,
|
|
)
|
|
import app.scodoc.sco_utils as scu
|
|
from app.but.prepajury_xl import ScoExcelBook
|
|
|
|
|
|
class Element:
|
|
def __init__(self, etudiant):
|
|
self.etudiant = etudiant
|
|
self.note = None
|
|
self.resultat = None
|
|
self.format = 0
|
|
|
|
def set_note(self, note):
|
|
self.note = note
|
|
|
|
def set_res(self, res):
|
|
self.resultat = res
|
|
|
|
def get_res(self):
|
|
return self.resultat
|
|
|
|
def get_note(self):
|
|
return self.note
|
|
|
|
|
|
class ElementUE(Element):
|
|
def __init__(self, etudiant):
|
|
super().__init__(etudiant)
|
|
self.status = None
|
|
|
|
def set_status(self, status):
|
|
self.status = status
|
|
|
|
|
|
class ElementNiveau(Element):
|
|
def __init__(self, etudiant, competence_id):
|
|
super().__init__(etudiant)
|
|
self.competence_id = competence_id
|
|
self.validation = None
|
|
self.ues = {}
|
|
|
|
def get_elem(self, periode=None):
|
|
if periode is None:
|
|
return self
|
|
return self.ues.get(periode, None)
|
|
|
|
def compute(self, rcue):
|
|
self.set_note(rcue.moy_rcue)
|
|
|
|
|
|
class ElementFormsemestre(Element):
|
|
def __init__(self, etudiant, formsemestre_desc: FormsemestreDesc = None):
|
|
super().__init__(etudiant)
|
|
self.formsemestre_desc = formsemestre_desc
|
|
self.formsemestre_id = formsemestre_desc.formsemestre_id
|
|
self.deca = None
|
|
self.ues = {}
|
|
|
|
def get_elem(self, competence_id=None):
|
|
if competence_id is None:
|
|
return self
|
|
return self.ues.get(competence_id, None)
|
|
|
|
|
|
class ElementAnnee(Element):
|
|
def __init__(self, etudiant):
|
|
super().__init__(etudiant)
|
|
self.formsemestres = {}
|
|
self.niveaux = {}
|
|
self.last = None
|
|
self.deca = None
|
|
|
|
def get_elem(self, competence_id=None, periode=None):
|
|
if competence_id is None and periode is None:
|
|
return self
|
|
elif competence_id is None:
|
|
return self.formsemestres.get(periode, None)
|
|
elif competence_id in self.niveaux:
|
|
return self.niveaux[competence_id].get_elem(periode)
|
|
else:
|
|
return None
|
|
|
|
def set_periode(self, periode, formsemestre_desc):
|
|
self.formsemestres[periode] = formsemestre_desc
|
|
|
|
def set_niveau(self, competence_id, elem_niveau):
|
|
self.niveaux[competence_id] = elem_niveau
|
|
|
|
def add_validation(self, validation):
|
|
competence_id = validation.ue1.niveau_competence.competence_id
|
|
self.niveaux[competence_id].set_res(validation.code)
|
|
|
|
def create_structure(self):
|
|
self.last = self.formsemestres.get(2, self.formsemestres.get(1, None))
|
|
if self.last is not None:
|
|
self.deca = jury_but.DecisionsProposeesAnnee(
|
|
self.etudiant.ident, self.last.formsemestre_desc.formsemestre
|
|
)
|
|
for niveau in self.deca.niveaux_competences:
|
|
competence_id = niveau.competence_id
|
|
elem_niveau = ElementNiveau(self.etudiant, competence_id)
|
|
self.niveaux[competence_id] = elem_niveau
|
|
for ue in self.deca.ues_impair:
|
|
competence_id = ue.niveau_competence.competence_id
|
|
periode = 1
|
|
elem_ue = ElementUE(self.etudiant)
|
|
self.niveaux[competence_id].ues[periode] = elem_ue
|
|
self.formsemestres[periode].ues[competence_id] = elem_ue
|
|
for ue in self.deca.ues_pair:
|
|
competence_id = ue.niveau_competence.competence_id
|
|
periode = 2
|
|
elem_ue = ElementUE(self.etudiant)
|
|
self.niveaux[competence_id].ues[periode] = elem_ue
|
|
self.formsemestres[periode].ues[competence_id] = elem_ue
|
|
|
|
def compute(self):
|
|
if self.last is not None:
|
|
self.set_res(self.deca.code_valide)
|
|
self.set_note(
|
|
self.last.formsemestre_desc.get_resultats().get_etud_moy_gen(
|
|
self.etudiant.ident.id
|
|
)
|
|
)
|
|
|
|
|
|
class EtudiantJury:
|
|
"""
|
|
Structure:
|
|
ident
|
|
formation
|
|
parcour
|
|
cursus
|
|
inscriptions*
|
|
current_formsemestre
|
|
absences_tot
|
|
absences_just
|
|
Annees*
|
|
nb_rcues
|
|
note
|
|
resultat
|
|
niveaux*
|
|
note
|
|
resultat
|
|
ues*
|
|
note
|
|
resultat
|
|
DUT
|
|
resultat
|
|
BUT
|
|
resultat
|
|
"""
|
|
|
|
annee_periode = {
|
|
1: ("BUT1", 1),
|
|
2: ("BUT1", 2),
|
|
3: ("BUT2", 1),
|
|
4: ("BUT2", 2),
|
|
5: ("BUT3", 1),
|
|
6: ("BUT3", 2),
|
|
}
|
|
|
|
def __init__(self, ident, contexte: "_Compilation"):
|
|
self.ident = ident
|
|
self.contexte = contexte
|
|
self.formation = contexte.formation
|
|
self.current_formsemestre = contexte.formsemestre
|
|
self.current_formsemestre_id = contexte.formsemestre.formsemestre_id
|
|
self.current_formsemestre_desc = contexte.get_semestredesc(
|
|
self.current_formsemestre_id
|
|
)
|
|
self.nbabs, self.nbabsjust = self.current_formsemestre.get_abs_count(ident.id)
|
|
self.cursus: EtudCursusBUT = EtudCursusBUT(ident, self.formation)
|
|
self.parcour = self.cursus.inscriptions[-1].parcour
|
|
# donnes propres à l étudiant (à remplir par fill_in)
|
|
self.history = [] # description historique de l etudiant
|
|
self.formsemestres = [] # liste historique des formsemestres
|
|
self.formsemestre_by_semestre = (
|
|
{}
|
|
) # semetre_id -> dernier FormSemestreDesc pour chaque semestre
|
|
self.formsemestre_by_annee = (
|
|
{}
|
|
) # annee -> dernier FormSemestreDesc pour chaque semestre
|
|
self.annees = {}
|
|
self.DUT = None # Résultat au DUT
|
|
self.BUT = None # Résultat au BUT
|
|
|
|
def get_elem(self, annee=None, competence_id=None, periode=None):
|
|
if annee is None:
|
|
return self
|
|
if annee in self.annees:
|
|
return self.annees[annee].get_elem(competence_id, periode)
|
|
return None
|
|
|
|
def get_desc(self, annee=None, competence_id=None, periode=None):
|
|
return self.parcour.get_desc(annee, competence_id, periode)
|
|
|
|
def compute_history(self):
|
|
# calcul historique
|
|
for inscription in sorted(
|
|
self.cursus.inscriptions, key=lambda x: x.formsemestre.date_debut
|
|
):
|
|
formsemestre = inscription.formsemestre
|
|
semestre_id = None
|
|
# if formsemestre.formation == self.formation:
|
|
if formsemestre.formation.is_apc():
|
|
formsemestre_id = formsemestre.formsemestre_id
|
|
formsemestre_desc = self.contexte.get_semestredesc(formsemestre_id)
|
|
semestre_id = formsemestre.semestre_id
|
|
self.formsemestres.append(formsemestre)
|
|
annee, periode = EtudiantJury.annee_periode[semestre_id]
|
|
self.formsemestre_by_semestre[semestre_id] = formsemestre_desc
|
|
self.formsemestre_by_annee[annee] = formsemestre_desc
|
|
etat = inscription.etat
|
|
Sx = f"S{semestre_id}"
|
|
if etat != "I":
|
|
Sx += " (Dem)" if etat == "D" else f"({etat})"
|
|
self.history.append(Sx)
|
|
|
|
def create_structure(self):
|
|
for annee, formsemestre_desc in self.formsemestre_by_annee.items():
|
|
elem_annee = ElementAnnee(self)
|
|
self.annees[annee] = elem_annee
|
|
|
|
for semestre_id, formsemestre_desc in self.formsemestre_by_semestre.items():
|
|
annee, periode = EtudiantJury.annee_periode[semestre_id]
|
|
elem_formsemestre = ElementFormsemestre(self.ident, formsemestre_desc)
|
|
self.annees[annee].set_periode(periode, elem_formsemestre)
|
|
|
|
for annee in self.annees:
|
|
self.annees[annee].create_structure()
|
|
|
|
def compute(self):
|
|
for annee in self.annees:
|
|
self.annees[annee].compute()
|
|
for (
|
|
competence_id,
|
|
validations,
|
|
) in self.cursus.validation_par_competence_et_annee.items():
|
|
for annee, validation in validations.items():
|
|
self.annees[annee].add_validation(validation)
|
|
|
|
def fill_in(self):
|
|
"""
|
|
Creation des donnees propres à l'étudiant
|
|
"""
|
|
self.compute_history()
|
|
# self.create_structure()
|
|
# self.compute()
|
|
# for (
|
|
# competence_id,
|
|
# validations_par_competence,
|
|
# ) in self.cursus.validation_par_competence_et_annee.items():
|
|
# for annee, validation in validations_par_competence.items():
|
|
# elem_annee = self.annees[annee]
|
|
# elem_formsemestre = elem_annee.formsemestres.get(
|
|
# periode, ElementFormsemestre(self, formsemestre_desc)
|
|
# )
|
|
# resultats = formsemestre_desc.get_resultats()
|
|
# ues = resultats.etud_ues(self.ident.etudid)
|
|
# for ue in ues:
|
|
# niveau_id = ue.niveau_competence_id
|
|
# competence_id = ue.niveau_competence.competence_id
|
|
# status = resultats.get_etud_ue_status(self.ident.etudid, ue.id)
|
|
# if competence_id not in self.annees[annee].niveaux:
|
|
# elem_niveau = ElementNiveau(self, validation)
|
|
# self.annees[annee].niveaux[competence_id] = elem_niveau
|
|
# else:
|
|
# elem_niveau = self.annees[annee].niveaux[competence_id]
|
|
# elem_ue = ElementUE(self, status)
|
|
# elem_niveau.ues[periode] = elem_ue
|
|
#
|
|
#
|
|
#
|
|
# for (
|
|
# competence_id,
|
|
# validation,
|
|
# ) in self.cursus.validation_par_competence_et_annee.items():
|
|
# self.elements_par_competence_annee_et_periode[competence_id] = {}
|
|
# for annee in validation:
|
|
# self.elements_par_competence_annee_et_periode[competence_id][
|
|
# annee
|
|
# ] = []
|
|
# self.deca_by_semestre[semestre_idx] = jury_but.DecisionsProposeesAnnee(
|
|
# self.ident, self.formsemestre_by_semestre[semestre_idx]
|
|
# )
|
|
# # niveau.add_ue_status(semestre_idx, status)
|
|
# if annee in self.deca:
|
|
# for rcue in self.deca[annee].rcues_annee:
|
|
# ue_id1 = rcue.ue_1.id
|
|
# self.notes_ues[ue_id1] = rcue.moy_ue_1
|
|
# ue_id2 = rcue.ue_2.id
|
|
# self.notes_ues[ue_id2] = rcue.moy_ue_2
|
|
# rcue_id = rcue.ue_1.niveau_competence_id
|
|
# self.notes_rcues[rcue_id] = rcue.moy_rcue
|
|
|
|
def get_note(self, annee, competence_id=None, periode=None):
|
|
elem: Element = self.get_elem(annee, competence_id, periode)
|
|
if elem:
|
|
return elem.get_note()
|
|
return "-"
|
|
|
|
def get_res(self, annee, competence_id=None, periode=None):
|
|
elem: Element = self.get_elem(annee, competence_id, periode)
|
|
if elem:
|
|
return elem.get_res()
|
|
return "-"
|
|
|
|
def get_data(self):
|
|
result = [
|
|
self.ident.id,
|
|
self.ident.code_nip,
|
|
self.ident.civilite,
|
|
self.ident.nom,
|
|
self.ident.prenom,
|
|
self.ident.etat_civil_pv(with_paragraph=False),
|
|
self.parcour.code,
|
|
", ".join(self.history),
|
|
]
|
|
return result
|
|
|
|
|
|
class _Compilation:
|
|
"""
|
|
structure:
|
|
semestres: formsemestre_id -> FormSemestreDesc
|
|
parcours: parcour_code -> ParcoursDesc
|
|
formation
|
|
"""
|
|
|
|
def __init__(self, formsemestre: FormSemestre):
|
|
self.semestres = {}
|
|
self.parcours = {}
|
|
formsemestre_id = formsemestre.formsemestre_id
|
|
self.formation: Formation = formsemestre.formation
|
|
self.formsemestre = formsemestre
|
|
self.add_semestre(formsemestre_id, formsemestre)
|
|
self.current_semestre = self.semestres[formsemestre_id]
|
|
# inventaire des semestres et parcours
|
|
for ident in (
|
|
self.semestres[formsemestre_id].get_resultats().get_inscrits(order_by="moy")
|
|
):
|
|
etudiant: EtudiantJury = EtudiantJury(
|
|
ident, self
|
|
) # initialise etudiant.cursus et etudiant.parcour
|
|
for inscription in etudiant.cursus.inscriptions:
|
|
formsemestre = inscription.formsemestre
|
|
if (
|
|
formsemestre.formation.referentiel_competence
|
|
== self.formation.referentiel_competence
|
|
):
|
|
self.add_semestre(formsemestre.formsemestre_id, formsemestre)
|
|
scodocParcour = etudiant.parcour
|
|
if scodocParcour is None:
|
|
parcourCode = "TC"
|
|
else:
|
|
parcourCode = scodocParcour.code
|
|
if parcourCode in self.parcours:
|
|
parcoursDesc = self.parcours[parcourCode]
|
|
else:
|
|
parcoursDesc = ParcoursDesc(self.formation, scodocParcour)
|
|
self.parcours[parcourCode] = parcoursDesc
|
|
parcoursDesc.add_etudiant(etudiant)
|
|
etudiant.fill_in()
|
|
|
|
def get_semestredesc(self, formsemestre_id):
|
|
return self.semestres.get(formsemestre_id, None)
|
|
|
|
def add_semestre(self, formsemestre_id, formsemestre=None):
|
|
if formsemestre_id not in self.semestres:
|
|
self.semestres[formsemestre_id] = FormsemestreDesc(
|
|
formsemestre_id, formsemestre
|
|
)
|
|
|
|
def add_parcours(self, scodoc_parcour: ApcParcours, etudiant: EtudiantJury):
|
|
parcour_code = scodoc_parcour.get("code", "TC")
|
|
if parcour_code not in self.parcours:
|
|
self.parcours[parcour_code] = ParcoursDesc(self.formation, scodoc_parcour)
|
|
self.parcours[parcour_code].add(etudiant)
|
|
|
|
def computes_decision(self):
|
|
pass
|
|
|
|
def make_excel(self, filename: str):
|
|
workbook = ScoExcelBook()
|
|
for parcoursCode, parcours in self.parcours.items():
|
|
parcours.generate(workbook)
|
|
|
|
mime, suffix = scu.get_mime_suffix("xlsx")
|
|
xls = workbook.generate()
|
|
return scu.send_file(xls, filename=filename, mime=mime, suffix=suffix)
|
|
|
|
|
|
def feuille_preparation_jury_but(formsemestre_id):
|
|
if not isinstance(formsemestre_id, int):
|
|
abort(404)
|
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
|
# res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
|
"""Feuille excel pour préparation des jurys adaptée pour le BUT."""
|
|
# breakpoint()
|
|
compilation = _Compilation(formsemestre)
|
|
# compilation.computes_decision()
|
|
filename = scu.sanitize_filename(
|
|
f"""{'jury'}-{formsemestre.titre_num()}-{time.strftime("%Y-%m-%d")}"""
|
|
)
|
|
return compilation.make_excel(filename)
|