Check APC conformity: cas UE de parcours

This commit is contained in:
Emmanuel Viennet 2022-12-17 17:27:14 -03:00 committed by iziram
parent 5258a570a6
commit 872e741d9f
4 changed files with 55 additions and 54 deletions

View File

@ -437,7 +437,7 @@ def load_evaluations_poids(moduleimpl_id: int) -> tuple[pd.DataFrame, list]:
def moduleimpl_is_conforme(
moduleimpl, evals_poids: pd.DataFrame, modules_coefficients: pd.DataFrame
moduleimpl, evals_poids: pd.DataFrame, modimpl_coefs_df: pd.DataFrame
) -> bool:
"""Vérifie que les évaluations de ce moduleimpl sont bien conformes
au PN.
@ -446,7 +446,7 @@ def moduleimpl_is_conforme(
Arguments:
evals_poids: DataFrame, colonnes: UEs, Lignes: EVALs
modules_coefficients: DataFrame, cols module_id, lignes UEs
modimpl_coefs_df: DataFrame, cols: modimpl_id, lignes: UEs du formsemestre
NB: les UEs dans evals_poids sont sans le bonus sport
"""
nb_evals, nb_ues = evals_poids.shape
@ -454,18 +454,18 @@ def moduleimpl_is_conforme(
return True # modules vides conformes
if nb_ues == 0:
return False # situation absurde (pas d'UE)
if len(modules_coefficients) != nb_ues:
if len(modimpl_coefs_df) != nb_ues:
# il arrive (#bug) que le cache ne soit pas à jour...
sco_cache.invalidate_formsemestre()
raise ScoBugCatcher("moduleimpl_is_conforme: nb ue incoherent")
if moduleimpl.module_id not in modules_coefficients:
if moduleimpl.id not in modimpl_coefs_df:
# soupçon de bug cache coef ?
sco_cache.invalidate_formsemestre()
raise ScoBugCatcher("Erreur 454 - merci de ré-essayer")
module_evals_poids = evals_poids.transpose().sum(axis=1) != 0
return all((modules_coefficients[moduleimpl.module_id] != 0).eq(module_evals_poids))
return all((modimpl_coefs_df[moduleimpl.id] != 0).eq(module_evals_poids))
class ModuleImplResultsClassic(ModuleImplResults):

View File

@ -62,7 +62,7 @@ class ModuleImpl(db.Model):
"""Invalide poids cachés"""
df_cache.EvaluationsPoidsCache.delete(self.id)
def check_apc_conformity(self) -> bool:
def check_apc_conformity(self, res: "ResultatsSemestreBUT") -> bool:
"""true si les poids des évaluations du module permettent de satisfaire
les coefficients du PN.
"""
@ -76,7 +76,7 @@ class ModuleImpl(db.Model):
return moy_mod.moduleimpl_is_conforme(
self,
self.get_evaluations_poids(),
self.module.formation.get_module_coefs(self.module.semestre_id),
res.modimpl_coefs_df,
)
def to_dict(self, convert_objects=False, with_module=True):

View File

@ -40,7 +40,7 @@ from app.comp import moy_mod
from app.comp.moy_mod import ModuleImplResults
from app.comp.res_compat import NotesTableCompat
from app.comp.res_but import ResultatsSemestreBUT
from app.models import FormSemestre
from app.models import FormSemestre, Module
from app.models.etudiants import Identite
from app.models.evaluations import Evaluation
from app.models.moduleimpls import ModuleImpl
@ -50,9 +50,7 @@ from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc.sco_etud import etud_sort_key
from app.scodoc import sco_evaluations
from app.scodoc import sco_evaluation_db
from app.scodoc import sco_formsemestre
from app.scodoc import sco_groups
from app.scodoc import sco_moduleimpl
from app.scodoc import sco_preferences
from app.scodoc import sco_users
import app.scodoc.sco_utils as scu
@ -198,8 +196,11 @@ def do_evaluation_listenotes(
elif tf[0] == -1:
return (
flask.redirect(
"%s/Notes/moduleimpl_status?moduleimpl_id=%s"
% (scu.ScoURL(), E["moduleimpl_id"])
url_for(
"notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept,
moduleimpl_id=E["moduleimpl_id"],
)
),
"",
)
@ -213,7 +214,7 @@ def do_evaluation_listenotes(
_make_table_notes(
tf[1],
evals,
format=format,
fmt=format,
note_sur_20=note_sur_20,
anonymous_listing=anonymous_listing,
group_ids=group_ids,
@ -228,45 +229,46 @@ def do_evaluation_listenotes(
def _make_table_notes(
html_form,
evals,
format="",
fmt: str = "",
note_sur_20=False,
anonymous_listing=False,
hide_groups=False,
with_emails=False,
group_ids=[],
group_ids: list[int] = None,
mode="module", # "eval" or "module"
):
) -> str:
"""Table liste notes (une seule évaluation ou toutes celles d'un module)"""
# Code à ré-écrire !
group_ids = group_ids or []
if not evals:
return "<p>Aucune évaluation !</p>"
E = evals[0]
moduleimpl_id = E["moduleimpl_id"]
modimpl_o = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id)[0]
module = models.Module.query.get(modimpl_o["module_id"])
modimpl = ModuleImpl.query.get_or_404(moduleimpl_id)
modimpl_o = modimpl.to_dict() # TODO temporaire - à refactorer
module: Module = modimpl.module
formsemestre: FormSemestre = modimpl.formsemestre
is_apc = module.formation.get_parcours().APC_SAE
if is_apc:
modimpl = ModuleImpl.query.get(moduleimpl_id)
is_conforme = modimpl.check_apc_conformity()
res: ResultatsSemestreBUT = res_sem.load_formsemestre_results(formsemestre)
is_conforme = modimpl.check_apc_conformity(res)
evals_poids, ues = moy_mod.load_evaluations_poids(moduleimpl_id)
if not ues:
is_apc = False
else:
evals_poids, ues = None, None
is_conforme = True
sem = sco_formsemestre.get_formsemestre(modimpl_o["formsemestre_id"])
# (debug) check that all evals are in same module:
for e in evals:
if e["moduleimpl_id"] != moduleimpl_id:
raise ValueError("invalid evaluations list")
if format == "xls":
if fmt == "xls":
keep_numeric = True # pas de conversion des notes en strings
else:
keep_numeric = False
# Si pas de groupe, affiche tout
if not group_ids:
group_ids = [sco_groups.get_default_group(modimpl_o["formsemestre_id"])]
group_ids = [sco_groups.get_default_group(formsemestre.id)]
groups = sco_groups.listgroups(group_ids)
gr_title = sco_groups.listgroups_abbrev(groups)
@ -275,7 +277,7 @@ def _make_table_notes(
if anonymous_listing:
columns_ids = ["code"] # cols in table
else:
if format == "xls" or format == "xml":
if fmt == "xls" or fmt == "xml":
columns_ids = ["nom", "prenom"]
else:
columns_ids = ["nomprenom"]
@ -326,7 +328,7 @@ def _make_table_notes(
continue
if etat == scu.INSCRIT: # si inscrit, indique groupe
groups = sco_groups.get_etud_groups(etudid, modimpl_o["formsemestre_id"])
groups = sco_groups.get_etud_groups(etudid, formsemestre.id)
grc = sco_groups.listgroups_abbrev(groups)
else:
if etat == scu.DEMISSION:
@ -348,7 +350,7 @@ def _make_table_notes(
"_nomprenom_target": url_for(
"notes.formsemestre_bulletinetud",
scodoc_dept=g.scodoc_dept,
formsemestre_id=modimpl_o["formsemestre_id"],
formsemestre_id=formsemestre.id,
etudid=etudid,
),
"_nomprenom_td_attrs": f"""id="{etudid}" class="etudinfo" data-sort="{etud.sort_key}" """,
@ -415,7 +417,7 @@ def _make_table_notes(
key_mgr,
note_sur_20,
keep_numeric,
format=format,
format=fmt,
)
columns_ids.append(e["evaluation_id"])
#
@ -431,7 +433,7 @@ def _make_table_notes(
# Moyenne de l'étudiant dans le module
# Affichée même en APC à titre indicatif
_add_moymod_column(
sem["formsemestre_id"],
formsemestre.id,
moduleimpl_id,
rows,
columns_ids,
@ -464,7 +466,7 @@ def _make_table_notes(
if with_emails:
columns_ids += ["email", "emailperso"]
# Ajoute lignes en tête et moyennes
if len(evals) > 0 and format != "bordereau":
if len(evals) > 0 and fmt != "bordereau":
rows_head = [row_coefs]
if is_apc:
rows_head.append(row_poids)
@ -472,7 +474,7 @@ def _make_table_notes(
rows = rows_head + rows
rows.append(row_moys)
# ajout liens HTMl vers affichage une evaluation:
if format == "html" and len(evals) > 1:
if fmt == "html" and len(evals) > 1:
rlinks = {"_table_part": "head"}
for e in evals:
rlinks[e["evaluation_id"]] = "afficher"
@ -488,11 +490,11 @@ def _make_table_notes(
rows.append(rlinks)
if len(evals) == 1: # colonne "Rem." seulement si une eval
if format == "html": # pas d'indication d'origine en pdf (pour affichage)
if fmt == "html": # pas d'indication d'origine en pdf (pour affichage)
columns_ids.append("expl_key")
elif format == "xls" or format == "xml":
elif fmt == "xls" or fmt == "xml":
columns_ids.append("comment")
elif format == "bordereau":
elif fmt == "bordereau":
columns_ids.append("signatures")
# titres divers:
@ -510,7 +512,7 @@ def _make_table_notes(
hh = "%s, %s (%d étudiants)" % (E["description"], gr_title, len(etudid_etats))
filename = scu.make_filename("notes_%s_%s" % (evalname, gr_title_filename))
if format == "bordereau":
if fmt == "bordereau":
hh = " %d étudiants" % (len(etudid_etats))
hh += " %d absent" % (nb_abs)
if nb_abs > 1:
@ -518,15 +520,13 @@ def _make_table_notes(
hh += ", %d en attente." % (nb_att)
# Attention: ReportLab supporte seulement '<br/>', pas '<br>' !
pdf_title = "<br/> BORDEREAU DE SIGNATURES"
pdf_title += "<br/><br/>%(titre)s" % sem
pdf_title += "<br/>(%(mois_debut)s - %(mois_fin)s)" % sem
pdf_title += " semestre %s %s" % (
sem["semestre_id"],
sem.get("modalite", ""),
)
pdf_title += f"<br/>Notes du module {module.code} - {module.titre}"
pdf_title += "<br/>Évaluation : %(description)s " % e
pdf_title = f"""<br/> BORDEREAU DE SIGNATURES
<br/><br/>{formsemestre.titre or ''}
<br/>({formsemestre.mois_debut()} - {formsemestre.mois_fin()})
semestre {formsemestre.semestre_id} {formsemestre.modalite or ""}
<br/>Notes du module {module.code} - {module.titre}
<br/>Évaluation : {e["description"]}
"""
if len(e["jour"]) > 0:
pdf_title += " (%(jour)s)" % e
pdf_title += "(noté sur %(note_max)s )<br/><br/>" % e
@ -551,12 +551,12 @@ def _make_table_notes(
else:
filename = scu.make_filename("notes_%s_%s" % (module.code, gr_title_filename))
title = f"Notes {module.type_name()} {module.code} {module.titre}"
title += " semestre %(titremois)s" % sem
title += f""" semestre {formsemestre.titre_mois()}"""
if gr_title and gr_title != "tous":
title += " %s" % gr_title
caption = title
html_next_section = ""
if format == "pdf" or format == "bordereau":
if fmt == "pdf" or fmt == "bordereau":
caption = "" # same as pdf_title
pdf_title = title
html_title = f"""<h2 class="formsemestre">Notes {module.type_name()} <a href="{
@ -580,17 +580,17 @@ def _make_table_notes(
origin=f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}",
caption=caption,
html_next_section=html_next_section,
page_title="Notes de " + sem["titremois"],
page_title="Notes de " + formsemestre.titre_mois(),
html_title=html_title,
pdf_title=pdf_title,
html_class="notes_evaluation",
preferences=sco_preferences.SemPreferences(modimpl_o["formsemestre_id"]),
preferences=sco_preferences.SemPreferences(formsemestre.id),
# html_generate_cells=False # la derniere ligne (moyennes) est incomplete
)
if format == "bordereau":
format = "pdf"
t = tab.make_page(format=format, with_html_headers=False)
if format != "html":
if fmt == "bordereau":
fmt = "pdf"
t = tab.make_page(format=fmt, with_html_headers=False)
if fmt != "html":
return t
if len(evals) > 1:
@ -599,7 +599,8 @@ def _make_table_notes(
if not e["eval_state"]["evalcomplete"]:
all_complete = False
if all_complete:
eval_info = '<span class="eval_info"><span class="eval_complete">Evaluations prises en compte dans les moyennes.</span>'
eval_info = """<span class="eval_info"><span class="eval_complete">Évaluations
prises en compte dans les moyennes.</span>"""
else:
eval_info = """<span class="eval_info help">
Les évaluations en vert et orange sont prises en compte dans les moyennes.

View File

@ -367,7 +367,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
H.append("</td></tr></table>")
#
if not modimpl.check_apc_conformity():
if not modimpl.check_apc_conformity(nt):
H.append(
"""<div class="warning conformite">Les poids des évaluations de ce module ne sont
pas encore conformes au PN.