ScoDoc-Lille/app/but/prepajury_but.py

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)