WIP: élimination de notes_table

This commit is contained in:
Emmanuel Viennet 2022-02-09 23:22:00 +01:00
parent d3fe08689e
commit 4465a735fc
12 changed files with 184 additions and 108 deletions

View File

@ -9,6 +9,7 @@
import datetime import datetime
from flask import url_for, g from flask import url_for, g
from app.models.formsemestre import FormSemestre
from app.scodoc import sco_utils as scu from app.scodoc import sco_utils as scu
from app.scodoc import sco_bulletins_json from app.scodoc import sco_bulletins_json
@ -18,30 +19,35 @@ from app.scodoc.sco_utils import fmt_note
from app.comp.res_but import ResultatsSemestreBUT from app.comp.res_but import ResultatsSemestreBUT
class BulletinBUT(ResultatsSemestreBUT): class BulletinBUT:
"""Génération du bulletin BUT. """Génération du bulletin BUT.
Cette classe génère des dictionnaires avec toutes les informations Cette classe génère des dictionnaires avec toutes les informations
du bulletin, qui sont immédiatement traduisibles en JSON. du bulletin, qui sont immédiatement traduisibles en JSON.
""" """
def __init__(self, formsemestre: FormSemestre):
""" """
self.res = ResultatsSemestreBUT(formsemestre)
def etud_ue_mod_results(self, etud, ue, modimpls) -> dict: def etud_ue_mod_results(self, etud, ue, modimpls) -> dict:
"dict synthèse résultats dans l'UE pour les modules indiqués" "dict synthèse résultats dans l'UE pour les modules indiqués"
res = self.res
d = {} d = {}
etud_idx = self.etud_index[etud.id] etud_idx = res.etud_index[etud.id]
if ue.type != UE_SPORT: if ue.type != UE_SPORT:
ue_idx = self.modimpl_coefs_df.index.get_loc(ue.id) ue_idx = res.modimpl_coefs_df.index.get_loc(ue.id)
etud_moy_module = self.sem_cube[etud_idx] # module x UE etud_moy_module = res.sem_cube[etud_idx] # module x UE
for modimpl in modimpls: for modimpl in modimpls:
if self.modimpl_inscr_df[modimpl.id][etud.id]: # si inscrit if res.modimpl_inscr_df[modimpl.id][etud.id]: # si inscrit
if ue.type != UE_SPORT: if ue.type != UE_SPORT:
coef = self.modimpl_coefs_df[modimpl.id][ue.id] coef = res.modimpl_coefs_df[modimpl.id][ue.id]
if coef > 0: if coef > 0:
d[modimpl.module.code] = { d[modimpl.module.code] = {
"id": modimpl.id, "id": modimpl.id,
"coef": coef, "coef": coef,
"moyenne": fmt_note( "moyenne": fmt_note(
etud_moy_module[ etud_moy_module[
self.modimpl_coefs_df.columns.get_loc(modimpl.id) res.modimpl_coefs_df.columns.get_loc(modimpl.id)
][ue_idx] ][ue_idx]
), ),
} }
@ -55,40 +61,39 @@ class BulletinBUT(ResultatsSemestreBUT):
def etud_ue_results(self, etud, ue): def etud_ue_results(self, etud, ue):
"dict synthèse résultats UE" "dict synthèse résultats UE"
res = self.res
d = { d = {
"id": ue.id, "id": ue.id,
"titre": ue.titre, "titre": ue.titre,
"numero": ue.numero, "numero": ue.numero,
"type": ue.type, "type": ue.type,
"ECTS": { "ECTS": {
"acquis": 0, # XXX TODO voir jury "acquis": 0, # XXX TODO voir jury #sco92
"total": ue.ects, "total": ue.ects,
}, },
"color": ue.color, "color": ue.color,
"competence": None, # XXX TODO lien avec référentiel "competence": None, # XXX TODO lien avec référentiel
"moyenne": None, "moyenne": None,
# Le bonus sport appliqué sur cette UE # Le bonus sport appliqué sur cette UE
"bonus": fmt_note(self.bonus_ues[ue.id][etud.id]) "bonus": fmt_note(res.bonus_ues[ue.id][etud.id])
if self.bonus_ues is not None and ue.id in self.bonus_ues if res.bonus_ues is not None and ue.id in res.bonus_ues
else fmt_note(0.0), else fmt_note(0.0),
"malus": self.malus[ue.id][etud.id], "malus": res.malus[ue.id][etud.id],
"capitalise": None, # "AAAA-MM-JJ" TODO "capitalise": None, # "AAAA-MM-JJ" TODO #sco92
"ressources": self.etud_ue_mod_results(etud, ue, self.ressources), "ressources": self.etud_ue_mod_results(etud, ue, res.ressources),
"saes": self.etud_ue_mod_results(etud, ue, self.saes), "saes": self.etud_ue_mod_results(etud, ue, res.saes),
} }
if ue.type != UE_SPORT: if ue.type != UE_SPORT:
if sco_preferences.get_preference( if sco_preferences.get_preference("bul_show_ue_rangs", res.formsemestre.id):
"bul_show_ue_rangs", self.formsemestre.id rangs, effectif = res.ue_rangs[ue.id]
):
rangs, effectif = self.ue_rangs[ue.id]
rang = rangs[etud.id] rang = rangs[etud.id]
else: else:
rang, effectif = "", 0 rang, effectif = "", 0
d["moyenne"] = { d["moyenne"] = {
"value": fmt_note(self.etud_moy_ue[ue.id][etud.id]), "value": fmt_note(res.etud_moy_ue[ue.id][etud.id]),
"min": fmt_note(self.etud_moy_ue[ue.id].min()), "min": fmt_note(res.etud_moy_ue[ue.id].min()),
"max": fmt_note(self.etud_moy_ue[ue.id].max()), "max": fmt_note(res.etud_moy_ue[ue.id].max()),
"moy": fmt_note(self.etud_moy_ue[ue.id].mean()), "moy": fmt_note(res.etud_moy_ue[ue.id].mean()),
"rang": rang, "rang": rang,
"total": effectif, # nb etud avec note dans cette UE "total": effectif, # nb etud avec note dans cette UE
} }
@ -98,7 +103,7 @@ class BulletinBUT(ResultatsSemestreBUT):
d["bonus_description"] = self.etud_bonus_description(etud.id) d["bonus_description"] = self.etud_bonus_description(etud.id)
modimpls_spo = [ modimpls_spo = [
modimpl modimpl
for modimpl in self.formsemestre.modimpls_sorted for modimpl in res.formsemestre.modimpls_sorted
if modimpl.module.ue.type == UE_SPORT if modimpl.module.ue.type == UE_SPORT
] ]
d["modules"] = self.etud_mods_results(etud, modimpls_spo) d["modules"] = self.etud_mods_results(etud, modimpls_spo)
@ -107,6 +112,7 @@ class BulletinBUT(ResultatsSemestreBUT):
def etud_mods_results(self, etud, modimpls) -> dict: def etud_mods_results(self, etud, modimpls) -> dict:
"""dict synthèse résultats des modules indiqués, """dict synthèse résultats des modules indiqués,
avec évaluations de chacun.""" avec évaluations de chacun."""
res = self.res
d = {} d = {}
# etud_idx = self.etud_index[etud.id] # etud_idx = self.etud_index[etud.id]
for modimpl in modimpls: for modimpl in modimpls:
@ -123,8 +129,8 @@ class BulletinBUT(ResultatsSemestreBUT):
# moy_indicative_mod = np.nanmean(self.sem_cube[etud_idx, mod_idx]) # moy_indicative_mod = np.nanmean(self.sem_cube[etud_idx, mod_idx])
# except RuntimeWarning: # all nans in np.nanmean # except RuntimeWarning: # all nans in np.nanmean
# pass # pass
modimpl_results = self.modimpls_results[modimpl.id] modimpl_results = res.modimpls_results[modimpl.id]
if self.modimpl_inscr_df[modimpl.id][etud.id]: # si inscrit if res.modimpl_inscr_df[modimpl.id][etud.id]: # si inscrit
d[modimpl.module.code] = { d[modimpl.module.code] = {
"id": modimpl.id, "id": modimpl.id,
"titre": modimpl.module.titre, "titre": modimpl.module.titre,
@ -153,7 +159,7 @@ class BulletinBUT(ResultatsSemestreBUT):
def etud_eval_results(self, etud, e) -> dict: def etud_eval_results(self, etud, e) -> dict:
"dict resultats d'un étudiant à une évaluation" "dict resultats d'un étudiant à une évaluation"
# eval_notes est une pd.Series avec toutes les notes des étudiants inscrits # eval_notes est une pd.Series avec toutes les notes des étudiants inscrits
eval_notes = self.modimpls_results[e.moduleimpl_id].evals_notes[e.id] eval_notes = self.res.modimpls_results[e.moduleimpl_id].evals_notes[e.id]
notes_ok = eval_notes.where(eval_notes > scu.NOTES_ABSENCE).dropna() notes_ok = eval_notes.where(eval_notes > scu.NOTES_ABSENCE).dropna()
d = { d = {
"id": e.id, "id": e.id,
@ -182,18 +188,18 @@ class BulletinBUT(ResultatsSemestreBUT):
def etud_bonus_description(self, etudid): def etud_bonus_description(self, etudid):
"""description du bonus affichée dans la section "UE bonus".""" """description du bonus affichée dans la section "UE bonus"."""
if self.bonus_ues is None or self.bonus_ues.shape[1] == 0: res = self.res
if res.bonus_ues is None or res.bonus_ues.shape[1] == 0:
return "" return ""
import random
bonus_vect = self.bonus_ues.loc[etudid] bonus_vect = res.bonus_ues.loc[etudid]
if bonus_vect.nunique() > 1: if bonus_vect.nunique() > 1:
# détail UE par UE # détail UE par UE
details = [ details = [
f"{fmt_note(bonus_vect[ue.id])} sur {ue.acronyme}" f"{fmt_note(bonus_vect[ue.id])} sur {ue.acronyme}"
for ue in self.ues for ue in res.ues
if self.modimpls_in_ue(ue.id, etudid) if res.modimpls_in_ue(ue.id, etudid)
and ue.id in self.bonus_ues and ue.id in res.bonus_ues
and bonus_vect[ue.id] > 0.0 and bonus_vect[ue.id] > 0.0
] ]
if details: if details:
@ -208,6 +214,7 @@ class BulletinBUT(ResultatsSemestreBUT):
Si force_publishing, rempli le bulletin même si bul_hide_xml est vrai Si force_publishing, rempli le bulletin même si bul_hide_xml est vrai
(bulletins non publiés). (bulletins non publiés).
""" """
res = self.res
etat_inscription = etud.etat_inscription(formsemestre.id) etat_inscription = etud.etat_inscription(formsemestre.id)
nb_inscrits = self.get_inscriptions_counts()[scu.INSCRIT] nb_inscrits = self.get_inscriptions_counts()[scu.INSCRIT]
published = (not formsemestre.bul_hide_xml) or force_publishing published = (not formsemestre.bul_hide_xml) or force_publishing
@ -235,7 +242,7 @@ class BulletinBUT(ResultatsSemestreBUT):
"etapes": [str(x.etape_apo) for x in formsemestre.etapes if x.etape_apo], "etapes": [str(x.etape_apo) for x in formsemestre.etapes if x.etape_apo],
"date_debut": formsemestre.date_debut.isoformat(), "date_debut": formsemestre.date_debut.isoformat(),
"date_fin": formsemestre.date_fin.isoformat(), "date_fin": formsemestre.date_fin.isoformat(),
"annee_universitaire": self.formsemestre.annee_scolaire_str(), "annee_universitaire": formsemestre.annee_scolaire_str(),
"numero": formsemestre.semestre_id, "numero": formsemestre.semestre_id,
"inscription": "", # inutilisé mais nécessaire pour le js de Seb. "inscription": "", # inutilisé mais nécessaire pour le js de Seb.
"groupes": [], # XXX TODO "groupes": [], # XXX TODO
@ -251,24 +258,24 @@ class BulletinBUT(ResultatsSemestreBUT):
semestre_infos.update( semestre_infos.update(
{ {
"notes": { # moyenne des moyennes générales du semestre "notes": { # moyenne des moyennes générales du semestre
"value": fmt_note(self.etud_moy_gen[etud.id]), "value": fmt_note(res.etud_moy_gen[etud.id]),
"min": fmt_note(self.etud_moy_gen.min()), "min": fmt_note(res.etud_moy_gen.min()),
"moy": fmt_note(self.etud_moy_gen.mean()), "moy": fmt_note(res.etud_moy_gen.mean()),
"max": fmt_note(self.etud_moy_gen.max()), "max": fmt_note(res.etud_moy_gen.max()),
}, },
"rang": { # classement wrt moyenne général, indicatif "rang": { # classement wrt moyenne général, indicatif
"value": self.etud_moy_gen_ranks[etud.id], "value": res.etud_moy_gen_ranks[etud.id],
"total": nb_inscrits, "total": nb_inscrits,
}, },
}, },
) )
d.update( d.update(
{ {
"ressources": self.etud_mods_results(etud, self.ressources), "ressources": self.etud_mods_results(etud, res.ressources),
"saes": self.etud_mods_results(etud, self.saes), "saes": self.etud_mods_results(etud, res.saes),
"ues": { "ues": {
ue.acronyme: self.etud_ue_results(etud, ue) ue.acronyme: self.etud_ue_results(etud, ue)
for ue in self.ues for ue in res.ues
if self.modimpls_in_ue( if self.modimpls_in_ue(
ue.id, etud.id ue.id, etud.id
) # si l'UE comporte des modules auxquels on est inscrit ) # si l'UE comporte des modules auxquels on est inscrit

View File

@ -20,7 +20,6 @@ from app.models import FormSemestre, Identite, ModuleImpl
from app.models import FormSemestreUECoef from app.models import FormSemestreUECoef
from app.models.ues import UniteEns from app.models.ues import UniteEns
from app.scodoc import sco_utils as scu from app.scodoc import sco_utils as scu
from app.scodoc import sco_evaluations
from app.scodoc.sco_cache import ResultatsSemestreCache from app.scodoc.sco_cache import ResultatsSemestreCache
from app.scodoc.sco_codes_parcours import UE_SPORT, ATT, DEF from app.scodoc.sco_codes_parcours import UE_SPORT, ATT, DEF
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoValueError
@ -388,7 +387,7 @@ class NotesTableCompat(ResultatsSemestre):
def compute_rangs(self): def compute_rangs(self):
"""Calcule les classements """Calcule les classements
Moyenne générale: etud_moy_gen_ranks Moyenne générale: etud_moy_gen_ranks
Par UE: Par UE (sauf ue bonus)
""" """
self.etud_moy_gen_ranks = moy_sem.comp_ranks_series(self.etud_moy_gen) self.etud_moy_gen_ranks = moy_sem.comp_ranks_series(self.etud_moy_gen)
for ue in self.formsemestre.query_ues(): for ue in self.formsemestre.query_ues():
@ -399,6 +398,37 @@ class NotesTableCompat(ResultatsSemestre):
) )
# .count() -> nb of non NaN values # .count() -> nb of non NaN values
def get_etud_ue_rang(self, ue_id, etudid) -> tuple[str, int]:
"""Le rang de l'étudiant dans cette ue
Result: rang:str, effectif:str
"""
rangs, effectif = self.ue_rangs[ue_id]
if rangs is not None:
rang = rangs[etudid]
else:
return "", ""
return rang, effectif
def etud_check_conditions_ues(self, etudid):
"""Vrai si les conditions sur les UE sont remplies.
Ne considère que les UE ayant des notes (moyenne calculée).
(les UE sans notes ne sont pas comptées comme sous la barre)
Prend en compte les éventuelles UE capitalisées.
Pour les parcours habituels, cela revient à vérifier que
les moyennes d'UE sont toutes > à leur barre (sauf celles sans notes)
Pour les parcours non standards (LP2014), cela peut être plus compliqué.
Return: True|False, message explicatif
"""
return self.parcours.check_barre_ues(
[
self.get_etud_ue_status(etudid, ue.id)
for ue in self.formsemestre.query_ues()
]
)
def get_etud_decision_ues(self, etudid: int) -> dict: def get_etud_decision_ues(self, etudid: int) -> dict:
"""Decisions du jury pour les UE de cet etudiant, ou None s'il n'y en pas eu. """Decisions du jury pour les UE de cet etudiant, ou None s'il n'y en pas eu.
Ne tient pas compte des UE capitalisées. Ne tient pas compte des UE capitalisées.
@ -521,6 +551,8 @@ class NotesTableCompat(ResultatsSemestre):
def get_evaluations_etats(self): def get_evaluations_etats(self):
"""[ {...evaluation et son etat...} ]""" """[ {...evaluation et son etat...} ]"""
# TODO: à moderniser # TODO: à moderniser
from app.scodoc import sco_evaluations
if not hasattr(self, "_evaluations_etats"): if not hasattr(self, "_evaluations_etats"):
self._evaluations_etats = sco_evaluations.do_evaluation_list_in_sem( self._evaluations_etats = sco_evaluations.do_evaluation_list_in_sem(
self.formsemestre.id self.formsemestre.id

View File

@ -37,6 +37,7 @@ Created on Fri Sep 9 09:15:05 2016
""" """
from app import log from app import log
from app.models.ues import UniteEns
from app.scodoc import sco_codes_parcours from app.scodoc import sco_codes_parcours
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_tag_module from app.scodoc import sco_tag_module
@ -238,7 +239,7 @@ class SemestreTag(pe_tagtable.TableTag):
etudid etudid
) # les ue capitalisées des étudiants ) # les ue capitalisées des étudiants
ue_capitalisees_id = [ ue_capitalisees_id = [
ue["ue_id"] for ue in ue_capitalisees ue.id for ue in ue_capitalisees
] # les id des ue capitalisées ] # les id des ue capitalisées
# Si le module ne fait pas partie des UE capitalisées # Si le module ne fait pas partie des UE capitalisées
@ -260,7 +261,7 @@ class SemestreTag(pe_tagtable.TableTag):
fids_prec = [ fids_prec = [
ue["formsemestre_id"] ue["formsemestre_id"]
for ue in ue_capitalisees for ue in ue_capitalisees
if ue["ue_code"] == modimpl["ue"]["ue_code"] if ue.ue_code == modimpl["ue"]["ue_code"]
] # and ue['semestre_id'] == semestre_id] ] # and ue['semestre_id'] == semestre_id]
if len(fids_prec) > 0: if len(fids_prec) > 0:
# => le formsemestre_id du semestre dont vient la capitalisation # => le formsemestre_id du semestre dont vient la capitalisation
@ -299,10 +300,12 @@ class SemestreTag(pe_tagtable.TableTag):
return (note, coeff_norm) return (note, coeff_norm)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
def get_ue_capitalisees(self, etudid): def get_ue_capitalisees(self, etudid) -> list[UniteEns]:
"""Renvoie la liste des ue_id effectivement capitalisées par un étudiant""" """Renvoie la liste des ue_id effectivement capitalisées par un étudiant"""
# return [ ue for ue in self.nt.ue_capitalisees[etudid] if self.nt.get_etud_ue_status(etudid,ue['ue_id'])['is_capitalized'] ] ue_ids = [
return self.nt.ue_capitalisees[etudid] ue_id for ue_id in self.nt.validations.ue_capitalisees.loc[etudid]["ue_id"]
]
return [UniteEns.query.get(ue_id) for ue_id in ue_ids]
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
def get_listesNotesEtCoeffsTagEtudiant(self, tag, etudid): def get_listesNotesEtCoeffsTagEtudiant(self, tag, etudid):

View File

@ -1314,10 +1314,6 @@ class NotesTable:
return self._evaluations_etats return self._evaluations_etats
def get_sem_evaluation_etat_list(self):
"""Liste des evaluations de ce semestre, avec leur etat"""
return self.get_evaluations_etats()
def get_mod_evaluation_etat_list(self, moduleimpl_id) -> list[dict]: def get_mod_evaluation_etat_list(self, moduleimpl_id) -> list[dict]:
"""Liste des évaluations de ce module""" """Liste des évaluations de ce module"""
return [ return [

View File

@ -366,9 +366,15 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
# log('cap details %s' % ue_status['moy']) # log('cap details %s' % ue_status['moy'])
if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]: if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]:
# detail des modules de l'UE capitalisee # detail des modules de l'UE capitalisee
nt_cap = sco_cache.NotesTableCache.get( # nt_cap = sco_cache.NotesTableCache.get(
# ue_status["formsemestre_id"]
# ) # > toutes notes
formsemestre_cap = FormSemestre.query.get_or_404(
ue_status["formsemestre_id"] ue_status["formsemestre_id"]
) # > toutes notes )
nt_cap: NotesTableCompat = res_sem.load_formsemestre_results(
formsemestre_cap
)
u["modules_capitalized"], _ = _ue_mod_bulletin( u["modules_capitalized"], _ = _ue_mod_bulletin(
etudid, etudid,

View File

@ -32,13 +32,14 @@ import datetime
import json import json
from app.but import bulletin_but from app.but import bulletin_but
from app.comp import res_sem
from app.comp.res_common import NotesTableCompat
from app.models.formsemestre import FormSemestre from app.models.formsemestre import FormSemestre
from app.models.etudiants import Identite from app.models.etudiants import Identite
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app.scodoc import sco_abs from app.scodoc import sco_abs
from app.scodoc import sco_cache
from app.scodoc import sco_edit_ue from app.scodoc import sco_edit_ue
from app.scodoc import sco_evaluation_db from app.scodoc import sco_evaluation_db
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
@ -90,11 +91,7 @@ def formsemestre_bulletinetud_published_dict(
etud = Identite.query.get(etudid) etud = Identite.query.get(etudid)
sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre_id)
if formsemestre.formation.is_apc(): nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
nt = bulletin_but.APCNotesTableCompat(formsemestre)
else:
nt = sco_cache.NotesTableCache.get(formsemestre_id)
d = {} d = {}
if (not sem["bul_hide_xml"]) or force_publishing: if (not sem["bul_hide_xml"]) or force_publishing:
@ -205,6 +202,7 @@ def formsemestre_bulletinetud_published_dict(
ects_txt = "" ects_txt = ""
else: else:
ects_txt = f"{ue['ects']:2.3g}" ects_txt = f"{ue['ects']:2.3g}"
rang, effectif = nt.get_etud_ue_rang(ue["ue_id"], etudid)
u = dict( u = dict(
id=ue["ue_id"], id=ue["ue_id"],
numero=scu.quote_xml_attr(ue["numero"]), numero=scu.quote_xml_attr(ue["numero"]),
@ -218,8 +216,8 @@ def formsemestre_bulletinetud_published_dict(
ue["moy"] ue["moy"]
), # CM : ajout pour faire apparaitre la moyenne des UE ), # CM : ajout pour faire apparaitre la moyenne des UE
), ),
rang=str(nt.ue_rangs[ue["ue_id"]][0][etudid]), rang=rang,
effectif=str(nt.ue_rangs[ue["ue_id"]][1]), effectif=effectif,
ects=ects_txt, ects=ects_txt,
code_apogee=scu.quote_xml_attr(ue["code_apogee"]), code_apogee=scu.quote_xml_attr(ue["code_apogee"]),
) )

View File

@ -44,6 +44,8 @@ import datetime
from xml.etree import ElementTree from xml.etree import ElementTree
from xml.etree.ElementTree import Element from xml.etree.ElementTree import Element
from app.comp import res_sem
from app.comp.res_common import NotesTableCompat
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app import log from app import log
@ -152,7 +154,8 @@ def make_xml_formsemestre_bulletinetud(
pid = partition["partition_id"] pid = partition["partition_id"]
partitions_etud_groups[pid] = sco_groups.get_etud_groups_in_partition(pid) partitions_etud_groups[pid] = sco_groups.get_etud_groups_in_partition(pid)
nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
ues = nt.get_ues_stat_dict() ues = nt.get_ues_stat_dict()
modimpls = nt.get_modimpls_dict() modimpls = nt.get_modimpls_dict()
nbetuds = len(nt.etud_moy_gen_ranks) nbetuds = len(nt.etud_moy_gen_ranks)
@ -230,8 +233,9 @@ def make_xml_formsemestre_bulletinetud(
except (ValueError, TypeError): except (ValueError, TypeError):
ects_txt = "" ects_txt = ""
x_ue.append(Element("ects", value=ects_txt)) x_ue.append(Element("ects", value=ects_txt))
x_ue.append(Element("rang", value=str(nt.ue_rangs[ue["ue_id"]][0][etudid]))) rang, effectif = nt.get_etud_ue_rang(ue["ue_id"], etudid)
x_ue.append(Element("effectif", value=str(nt.ue_rangs[ue["ue_id"]][1]))) x_ue.append(Element("rang", value=str(rang)))
x_ue.append(Element("effectif", value=str(effectif)))
# Liste les modules de l'UE # Liste les modules de l'UE
ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]] ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]]
for modimpl in ue_modimpls: for modimpl in ue_modimpls:

View File

@ -31,13 +31,17 @@ import datetime
import operator import operator
import time import time
import flask
from flask import url_for from flask import url_for
from flask import g from flask import g
from flask_login import current_user from flask_login import current_user
from flask import request from flask import request
from app import log from app import log
from app.comp import res_sem
from app.comp.res_common import NotesTableCompat
from app.models import FormSemestre
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType from app.scodoc.sco_utils import ModuleType
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
@ -379,10 +383,9 @@ def _eval_etat(evals):
def do_evaluation_etat_in_sem(formsemestre_id): def do_evaluation_etat_in_sem(formsemestre_id):
"""-> nb_eval_completes, nb_evals_en_cours, nb_evals_vides, """-> nb_eval_completes, nb_evals_en_cours, nb_evals_vides,
date derniere modif, attente""" date derniere modif, attente"""
nt = sco_cache.NotesTableCache.get( formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
formsemestre_id nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
) # > liste evaluations et moduleimpl en attente evals = nt.get_evaluations_etats()
evals = nt.get_sem_evaluation_etat_list()
etat = _eval_etat(evals) etat = _eval_etat(evals)
# Ajoute information sur notes en attente # Ajoute information sur notes en attente
etat["attente"] = len(nt.get_moduleimpls_attente()) > 0 etat["attente"] = len(nt.get_moduleimpls_attente()) > 0
@ -403,7 +406,7 @@ def formsemestre_evaluations_cal(formsemestre_id):
sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre_id)
nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations
evals = nt.get_sem_evaluation_etat_list() evals = nt.get_evaluations_etats()
nb_evals = len(evals) nb_evals = len(evals)
color_incomplete = "#FF6060" color_incomplete = "#FF6060"
@ -538,7 +541,7 @@ def formsemestre_evaluations_delai_correction(formsemestre_id, format="html"):
sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre_id)
nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations
evals = nt.get_sem_evaluation_etat_list() evals = nt.get_evaluations_etats()
T = [] T = []
for e in evals: for e in evals:
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=e["moduleimpl_id"])[0] M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=e["moduleimpl_id"])[0]

View File

@ -342,7 +342,7 @@ def do_formsemestre_uecoef_delete(cnx, formsemestre_id, ue_id):
formsemestre_uecoef_delete(cnx, coefs[0]["formsemestre_uecoef_id"]) formsemestre_uecoef_delete(cnx, coefs[0]["formsemestre_uecoef_id"])
def read_formsemestre_etapes(formsemestre_id): def read_formsemestre_etapes(formsemestre_id): # OBSOLETE
"""recupere liste des codes etapes associés à ce semestre """recupere liste des codes etapes associés à ce semestre
:returns: liste d'instance de ApoEtapeVDI :returns: liste d'instance de ApoEtapeVDI
""" """

View File

@ -28,7 +28,10 @@
"""Semestres: gestion parcours DUT (Arreté du 13 août 2005) """Semestres: gestion parcours DUT (Arreté du 13 août 2005)
""" """
from app.models.ues import UniteEns from app.comp import res_sem
from app.comp.res_common import NotesTableCompat
from app.models import FormSemestre, UniteEns
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
from app import log from app import log
@ -108,9 +111,11 @@ class DecisionSem(object):
def SituationEtudParcours(etud, formsemestre_id): def SituationEtudParcours(etud, formsemestre_id):
"""renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)""" """renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)"""
nt = sco_cache.NotesTableCache.get( # nt = sco_cache.NotesTableCache.get(
formsemestre_id # formsemestre_id
) # > get_etud_decision_sem, get_etud_moy_gen, get_ues_stat_dict, get_etud_ue_status, etud_check_conditions_ues # ) # > get_etud_decision_sem, get_etud_moy_gen, get_ues_stat_dict, get_etud_ue_status, etud_check_conditions_ues
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
parcours = nt.parcours parcours = nt.parcours
# #
if parcours.ECTS_ONLY: if parcours.ECTS_ONLY:
@ -131,7 +136,7 @@ class SituationEtudParcoursGeneric(object):
self.formsemestre_id = formsemestre_id self.formsemestre_id = formsemestre_id
self.sem = sco_formsemestre.get_formsemestre(formsemestre_id) self.sem = sco_formsemestre.get_formsemestre(formsemestre_id)
self.nt = nt self.nt = nt
self.formation = self.nt.formation self.formation = self.nt.formsemestre.formation
self.parcours = self.nt.parcours self.parcours = self.nt.parcours
# Ce semestre est-il le dernier de la formation ? (e.g. semestre 4 du DUT) # Ce semestre est-il le dernier de la formation ? (e.g. semestre 4 du DUT)
# pour le DUT, le dernier est toujours S4. # pour le DUT, le dernier est toujours S4.
@ -295,11 +300,15 @@ class SituationEtudParcoursGeneric(object):
for sem in self.get_semestres(): for sem in self.get_semestres():
if ( if (
sem["semestre_id"] == n1 sem["semestre_id"] == n1
and sem["formation_code"] == self.formation["formation_code"] and sem["formation_code"] == self.formation.formation_code
): ):
nt = sco_cache.NotesTableCache.get( # nt = sco_cache.NotesTableCache.get(
sem["formsemestre_id"] # sem["formsemestre_id"]
) # > get_etud_decision_sem # ) # > get_etud_decision_sem
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
nt: NotesTableCompat = res_sem.load_formsemestre_results(
formsemestre
)
decision = nt.get_etud_decision_sem(self.etudid) decision = nt.get_etud_decision_sem(self.etudid)
if decision and ( if decision and (
code_semestre_validant(decision["code"]) code_semestre_validant(decision["code"])
@ -312,10 +321,12 @@ class SituationEtudParcoursGeneric(object):
"""True si les semestres dont les indices sont donnés en argument (modifié) """True si les semestres dont les indices sont donnés en argument (modifié)
sont validés. En sortie, sem_idx_set contient ceux qui n'ont pas été validés.""" sont validés. En sortie, sem_idx_set contient ceux qui n'ont pas été validés."""
for sem in self.get_semestres(): for sem in self.get_semestres():
if sem["formation_code"] == self.formation["formation_code"]: if sem["formation_code"] == self.formation.formation_code:
nt = sco_cache.NotesTableCache.get( # nt = sco_cache.NotesTableCache.get(
sem["formsemestre_id"] # sem["formsemestre_id"]
) # > get_etud_decision_sem # ) # > get_etud_decision_sem
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
decision = nt.get_etud_decision_sem(self.etudid) decision = nt.get_etud_decision_sem(self.etudid)
if decision and code_semestre_validant(decision["code"]): if decision and code_semestre_validant(decision["code"]):
# validé # validé
@ -331,9 +342,11 @@ class SituationEtudParcoursGeneric(object):
ue_acros = {} # acronyme ue : 1 ue_acros = {} # acronyme ue : 1
nb_max_ue = 0 nb_max_ue = 0
for sem in sems: for sem in sems:
nt = sco_cache.NotesTableCache.get( # nt = sco_cache.NotesTableCache.get(
sem["formsemestre_id"] # sem["formsemestre_id"]
) # > get_ues_stat_dict # ) # > get_ues_stat_dict
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
ues = nt.get_ues_stat_dict(filter_sport=True) ues = nt.get_ues_stat_dict(filter_sport=True)
for ue in ues: for ue in ues:
ue_acros[ue["acronyme"]] = 1 ue_acros[ue["acronyme"]] = 1
@ -401,9 +414,11 @@ class SituationEtudParcoursGeneric(object):
if not sem: if not sem:
code = "" # non inscrit à ce semestre code = "" # non inscrit à ce semestre
else: else:
nt = sco_cache.NotesTableCache.get( # nt = sco_cache.NotesTableCache.get(
sem["formsemestre_id"] # sem["formsemestre_id"]
) # > get_etud_decision_sem # ) # > get_etud_decision_sem
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
decision = nt.get_etud_decision_sem(self.etudid) decision = nt.get_etud_decision_sem(self.etudid)
if decision: if decision:
code = decision["code"] code = decision["code"]
@ -459,7 +474,7 @@ class SituationEtudParcoursGeneric(object):
prev = None prev = None
while i >= 0: while i >= 0:
if ( if (
self.sems[i]["formation_code"] == self.formation["formation_code"] self.sems[i]["formation_code"] == self.formation.formation_code
and self.sems[i]["semestre_id"] == cur["semestre_id"] - 1 and self.sems[i]["semestre_id"] == cur["semestre_id"] - 1
): ):
prev = self.sems[i] prev = self.sems[i]
@ -471,8 +486,9 @@ class SituationEtudParcoursGeneric(object):
# Verifications basiques: # Verifications basiques:
# ? # ?
# Code etat du semestre precedent: # Code etat du semestre precedent:
nt = sco_cache.NotesTableCache.get(prev["formsemestre_id"]) # nt = sco_cache.NotesTableCache.get(prev["formsemestre_id"])
# > get_etud_decision_sem, get_etud_moy_gen, etud_check_conditions_ues formsemestre = FormSemestre.query.get_or_404(prev["formsemestre_id"])
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
self.prev_decision = nt.get_etud_decision_sem(self.etudid) self.prev_decision = nt.get_etud_decision_sem(self.etudid)
self.prev_moy_gen = nt.get_etud_moy_gen(self.etudid) self.prev_moy_gen = nt.get_etud_moy_gen(self.etudid)
self.prev_barres_ue_ok = nt.etud_check_conditions_ues(self.etudid)[0] self.prev_barres_ue_ok = nt.etud_check_conditions_ues(self.etudid)[0]
@ -526,11 +542,15 @@ class SituationEtudParcoursGeneric(object):
validated = False validated = False
for sem in self.sems: for sem in self.sems:
if ( if (
sem["formation_code"] == self.formation["formation_code"] sem["formation_code"] == self.formation.formation_code
and sem["semestre_id"] == s and sem["semestre_id"] == s
): ):
nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) # nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"])
# > get_etud_decision_sem # > get_etud_decision_sem
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
nt: NotesTableCompat = res_sem.load_formsemestre_results(
formsemestre
)
decision = nt.get_etud_decision_sem(self.etudid) decision = nt.get_etud_decision_sem(self.etudid)
if decision and code_semestre_validant(decision["code"]): if decision and code_semestre_validant(decision["code"]):
validated = True validated = True
@ -642,7 +662,7 @@ class SituationEtudParcoursGeneric(object):
cnx, cnx,
{ {
"etudid": self.etudid, "etudid": self.etudid,
"formation_code": self.formation["formation_code"], "formation_code": self.formation.formation_code,
"semestre_id": next_semestre_id, "semestre_id": next_semestre_id,
"origin_formsemestre_id": self.formsemestre_id, "origin_formsemestre_id": self.formsemestre_id,
}, },
@ -904,9 +924,11 @@ def formsemestre_validate_ues(formsemestre_id, etudid, code_etat_sem, assiduite)
""" """
valid_semestre = CODES_SEM_VALIDES.get(code_etat_sem, False) valid_semestre = CODES_SEM_VALIDES.get(code_etat_sem, False)
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
nt = sco_cache.NotesTableCache.get( # nt = sco_cache.NotesTableCache.get(
formsemestre_id # formsemestre_id
) # > get_ues_stat_dict, get_etud_ue_status # ) # > get_ues_stat_dict, get_etud_ue_status
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
ue_ids = [x["ue_id"] for x in nt.get_ues_stat_dict(filter_sport=True)] ue_ids = [x["ue_id"] for x in nt.get_ues_stat_dict(filter_sport=True)]
for ue_id in ue_ids: for ue_id in ue_ids:
ue_status = nt.get_etud_ue_status(etudid, ue_id) ue_status = nt.get_etud_ue_status(etudid, ue_id)

View File

@ -53,7 +53,10 @@ from reportlab.lib import styles
import flask import flask
from flask import url_for, g, request from flask import url_for, g, request
from app.models.ues import UniteEns
from app.comp import res_sem
from app.comp.res_common import NotesTableCompat
from app.models import FormSemestre, UniteEns
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
@ -98,9 +101,9 @@ def _descr_decisions_ues(nt, etudid, decisions_ue, decision_sem):
except: except:
log("descr_decisions_ues: ue_id=%s decisions_ue=%s" % (ue_id, decisions_ue)) log("descr_decisions_ues: ue_id=%s decisions_ue=%s" % (ue_id, decisions_ue))
# Les UE capitalisées dans d'autres semestres: # Les UE capitalisées dans d'autres semestres:
for ue in nt.ue_capitalisees[etudid]: for ue_id in nt.validations.ue_capitalisees.loc[etudid]["ue_id"]:
try: try:
uelist.append(nt.get_etud_ue_status(etudid, ue["ue_id"])["ue"]) uelist.append(nt.get_etud_ue_status(etudid, ue_id)["ue"])
except KeyError: except KeyError:
pass pass
uelist.sort(key=itemgetter("numero")) uelist.sort(key=itemgetter("numero"))
@ -213,9 +216,11 @@ def dict_pvjury(
'decisions_dict' : { etudid : decision (comme ci-dessus) }, 'decisions_dict' : { etudid : decision (comme ci-dessus) },
} }
""" """
nt = sco_cache.NotesTableCache.get( # nt = sco_cache.NotesTableCache.get(
formsemestre_id # formsemestre_id
) # > get_etudids, get_etud_etat, get_etud_decision_sem, get_etud_decision_ues # ) # > get_etudids, get_etud_etat, get_etud_decision_sem, get_etud_decision_ues
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
if etudids is None: if etudids is None:
etudids = nt.get_etudids() etudids = nt.get_etudids()
if not etudids: if not etudids:

View File

@ -977,7 +977,7 @@ def _formsemestre_recapcomplet_json(
def formsemestres_bulletins(annee_scolaire): def formsemestres_bulletins(annee_scolaire):
"""Tous les bulletins des semestres publiés des semestres de l'année indiquée. """Tous les bulletins des semestres publiés des semestres de l'année indiquée.
:param annee_scolaire(int): année de début de l'année scoalaire :param annee_scolaire(int): année de début de l'année scolaire
:returns: JSON :returns: JSON
""" """
jslist = [] jslist = []