Bulletins: evals rat. et sessions 2. Fix #492.
This commit is contained in:
parent
219a3c2811
commit
acd1b36d72
@ -13,7 +13,7 @@ import numpy as np
|
||||
from flask import g, has_request_context, url_for
|
||||
|
||||
from app.comp.res_but import ResultatsSemestreBUT
|
||||
from app.models import FormSemestre, Identite
|
||||
from app.models import Evaluation, FormSemestre, Identite
|
||||
from app.models.groups import GroupDescr
|
||||
from app.models.ues import UniteEns
|
||||
from app.scodoc import sco_bulletins, sco_utils as scu
|
||||
@ -249,7 +249,7 @@ class BulletinBUT:
|
||||
}
|
||||
return d
|
||||
|
||||
def etud_eval_results(self, etud, e) -> dict:
|
||||
def etud_eval_results(self, etud, e: Evaluation) -> dict:
|
||||
"dict resultats d'un étudiant à une évaluation"
|
||||
# eval_notes est une pd.Series avec toutes les notes des étudiants inscrits
|
||||
eval_notes = self.res.modimpls_results[e.moduleimpl_id].evals_notes[e.id]
|
||||
@ -265,12 +265,14 @@ class BulletinBUT:
|
||||
poids = collections.defaultdict(lambda: 0.0)
|
||||
d = {
|
||||
"id": e.id,
|
||||
"description": e.description,
|
||||
"coef": fmt_note(e.coefficient)
|
||||
if e.evaluation_type == scu.EVALUATION_NORMALE
|
||||
else None,
|
||||
"date": e.jour.isoformat() if e.jour else None,
|
||||
"description": e.description,
|
||||
"evaluation_type": e.evaluation_type,
|
||||
"heure_debut": e.heure_debut.strftime("%H:%M") if e.heure_debut else None,
|
||||
"heure_fin": e.heure_fin.strftime("%H:%M") if e.heure_debut else None,
|
||||
"coef": fmt_note(e.coefficient),
|
||||
"poids": poids,
|
||||
"note": {
|
||||
"value": fmt_note(
|
||||
eval_notes[etud.id],
|
||||
@ -280,6 +282,7 @@ class BulletinBUT:
|
||||
"max": fmt_note(notes_ok.max()),
|
||||
"moy": fmt_note(notes_ok.mean()),
|
||||
},
|
||||
"poids": poids,
|
||||
"url": url_for(
|
||||
"notes.evaluation_listenotes",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
|
@ -13,6 +13,7 @@ from reportlab.platypus import Paragraph, Spacer
|
||||
from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
|
||||
from app.scodoc import gen_tables
|
||||
from app.scodoc.sco_codes_parcours import UE_SPORT
|
||||
from app.scodoc import sco_utils as scu
|
||||
|
||||
|
||||
class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
@ -312,18 +313,19 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
|
||||
]
|
||||
return col_keys, rows, pdf_style, col_widths
|
||||
|
||||
def evaluations_rows(self, rows, evaluations, ue_acros=()):
|
||||
def evaluations_rows(self, rows, evaluations: list[dict], ue_acros=()):
|
||||
"lignes des évaluations"
|
||||
for e in evaluations:
|
||||
coef = e["coef"] if e["evaluation_type"] == scu.EVALUATION_NORMALE else "*"
|
||||
t = {
|
||||
"titre": f"{e['description'] or ''}",
|
||||
"moyenne": e["note"]["value"],
|
||||
"_moyenne_pdf": Paragraph(
|
||||
f"""<para align=right>{e["note"]["value"]}</para>"""
|
||||
),
|
||||
"coef": e["coef"],
|
||||
"coef": coef,
|
||||
"_coef_pdf": Paragraph(
|
||||
f"<para align=right fontSize={self.small_fontsize}><i>{e['coef']}</i></para>"
|
||||
f"<para align=right fontSize={self.small_fontsize}><i>{coef}</i></para>"
|
||||
),
|
||||
"_pdf_style": [
|
||||
(
|
||||
|
@ -90,7 +90,9 @@ def pvjury_table_but(formsemestre_id: int, format="html"):
|
||||
if deca
|
||||
else "-",
|
||||
"decision_but": deca.code_valide if deca else "",
|
||||
"devenir": ", ".join([f"S{i}" for i in deca.get_autorisations_passage()]),
|
||||
"devenir": ", ".join([f"S{i}" for i in deca.get_autorisations_passage()])
|
||||
if deca
|
||||
else "",
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
@ -124,7 +124,7 @@ class ModuleImplResults:
|
||||
Évaluation "complete" (prise en compte dans les calculs) si:
|
||||
- soit tous les étudiants inscrits au module ont des notes
|
||||
- soit elle a été déclarée "à prise en compte immédiate" (publish_incomplete)
|
||||
|
||||
ou est une évaluation de rattrapage ou de session 2
|
||||
Évaluation "attente" (prise en compte dans les calculs, mais il y
|
||||
manque des notes) ssi il y a des étudiants inscrits au semestre et au module
|
||||
qui ont des notes ATT.
|
||||
@ -148,11 +148,14 @@ class ModuleImplResults:
|
||||
eval_df = self._load_evaluation_notes(evaluation)
|
||||
# is_complete ssi tous les inscrits (non dem) au semestre ont une note
|
||||
# ou évaluation déclarée "à prise en compte immédiate"
|
||||
# Les évaluations de rattrapage et 2eme session sont toujours incomplètes
|
||||
# car on calcule leur moyenne à part.
|
||||
# Les évaluations de rattrapage et 2eme session sont toujours complètes
|
||||
|
||||
etudids_sans_note = inscrits_module - set(eval_df.index) # sans les dem.
|
||||
is_complete = (evaluation.evaluation_type == scu.EVALUATION_NORMALE) and (
|
||||
evaluation.publish_incomplete or (not etudids_sans_note)
|
||||
is_complete = (
|
||||
(evaluation.evaluation_type == scu.EVALUATION_RATTRAPAGE)
|
||||
or (evaluation.evaluation_type == scu.EVALUATION_SESSION2)
|
||||
or (evaluation.publish_incomplete)
|
||||
or (not etudids_sans_note)
|
||||
)
|
||||
self.evaluations_completes.append(is_complete)
|
||||
self.evaluations_completes_dict[evaluation.id] = is_complete
|
||||
|
@ -30,6 +30,7 @@
|
||||
"""
|
||||
import email
|
||||
import time
|
||||
import numpy as np
|
||||
|
||||
from flask import g, request
|
||||
from flask import flash, jsonify, render_template, url_for
|
||||
@ -575,18 +576,20 @@ def _ue_mod_bulletin(
|
||||
else:
|
||||
e["name"] = "Points de bonus sur cette UE"
|
||||
else:
|
||||
e["name"] = e["description"] or "le %s" % e["jour"]
|
||||
e["target_html"] = (
|
||||
"evaluation_listenotes?evaluation_id=%s&format=html&tf_submitted=1"
|
||||
% e["evaluation_id"]
|
||||
e["name"] = e["description"] or f"le {e['jour']}"
|
||||
e["target_html"] = url_for(
|
||||
"notes.evaluation_listenotes",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
evaluation_id=e["evaluation_id"],
|
||||
format="html",
|
||||
tf_submitted=1,
|
||||
)
|
||||
e["name_html"] = '<a class="bull_link" href="%s">%s</a>' % (
|
||||
e["target_html"],
|
||||
e["name"],
|
||||
)
|
||||
val = e["notes"].get(etudid, {"value": "NP"})[
|
||||
"value"
|
||||
] # NA si etud demissionnaire
|
||||
e[
|
||||
"name_html"
|
||||
] = f"""<a class="bull_link" href="{
|
||||
e['target_html']}">{e['name']}</a>"""
|
||||
val = e["notes"].get(etudid, {"value": "NP"})["value"]
|
||||
# val est NP si etud demissionnaire
|
||||
if val == "NP":
|
||||
e["note_txt"] = "nd"
|
||||
e["note_html"] = '<span class="note_nd">nd</span>'
|
||||
@ -604,13 +607,18 @@ def _ue_mod_bulletin(
|
||||
if e["evaluation_type"] == scu.EVALUATION_RATTRAPAGE:
|
||||
e["coef_txt"] = "rat."
|
||||
elif e["evaluation_type"] == scu.EVALUATION_SESSION2:
|
||||
e["coef_txt"] = "sess. 2"
|
||||
e["coef_txt"] = "Ses. 2"
|
||||
if e["etat"]["evalattente"]:
|
||||
mod_attente = True # une eval en attente dans ce module
|
||||
if (not is_malus) or (val != "NP"):
|
||||
mod["evaluations"].append(
|
||||
e
|
||||
) # ne liste pas les eval malus sans notes
|
||||
if ((not is_malus) or (val != "NP")) and (
|
||||
(
|
||||
e["evaluation_type"] == scu.EVALUATION_NORMALE
|
||||
or not np.isnan(val)
|
||||
)
|
||||
):
|
||||
# ne liste pas les eval malus sans notes
|
||||
# ni les rattrapages et sessions 2 si pas de note
|
||||
mod["evaluations"].append(e)
|
||||
|
||||
# Evaluations incomplètes ou futures:
|
||||
mod["evaluations_incompletes"] = []
|
||||
|
@ -150,7 +150,7 @@ class ScoInvalidIdType(ScoValueError):
|
||||
</p>
|
||||
<p> Si le problème persiste, merci de contacter l'assistance
|
||||
via la liste de diffusion <a href="{scu.SCO_USERS_LIST}">Notes</a>
|
||||
ou le salon Discord.
|
||||
ou de préférence le <a href="{scu.SCO_DISCORD_ASSISTANCE}">salon Discord</a>.
|
||||
</p>
|
||||
<p>Message serveur: <tt>{msg}</tt></p>
|
||||
"""
|
||||
|
@ -40,12 +40,14 @@ from app.comp import res_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import Module
|
||||
from app.models.formsemestre import FormSemestre
|
||||
from app.models.moduleimpls import ModuleImpl
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_utils import ModuleType
|
||||
import app.scodoc.notesdb as ndb
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.scodoc.sco_exceptions import ScoValueError, ScoInvalidDateError
|
||||
from app.scodoc.sco_exceptions import (
|
||||
ScoValueError,
|
||||
ScoInvalidDateError,
|
||||
ScoInvalidIdType,
|
||||
)
|
||||
from app.scodoc import html_sco_header
|
||||
from app.scodoc import htmlutils
|
||||
from app.scodoc import sco_abs
|
||||
@ -58,7 +60,6 @@ from app.scodoc import sco_evaluations
|
||||
from app.scodoc import sco_evaluation_db
|
||||
from app.scodoc import sco_formations
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_formsemestre_edit
|
||||
from app.scodoc import sco_formsemestre_inscriptions
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_moduleimpl
|
||||
@ -1008,6 +1009,10 @@ Il y a des notes en attente ! Le classement des étudiants n'a qu'une valeur ind
|
||||
def formsemestre_status(formsemestre_id=None):
|
||||
"""Tableau de bord semestre HTML"""
|
||||
# porté du DTML
|
||||
if formsemestre_id is not None and not isinstance(formsemestre_id, int):
|
||||
raise ScoInvalidIdType(
|
||||
"formsemestre_bulletinetud: formsemestre_id must be an integer !"
|
||||
)
|
||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
modimpls = sco_moduleimpl.moduleimpl_withmodule_list(
|
||||
formsemestre_id=formsemestre_id
|
||||
|
@ -740,7 +740,8 @@ def scolars_import_admission(datafile, formsemestre_id=None, type_admission=None
|
||||
_ADM_PATTERN = re.compile(r"[\W]+", re.UNICODE) # supprime tout sauf alphanum
|
||||
|
||||
|
||||
def adm_normalize_string(s): # normalize unicode title
|
||||
def adm_normalize_string(s):
|
||||
"normalize unicode title"
|
||||
return scu.suppress_accents(_ADM_PATTERN.sub("", s.strip().lower())).replace(
|
||||
"_", ""
|
||||
)
|
||||
@ -750,16 +751,15 @@ def adm_get_fields(titles, formsemestre_id):
|
||||
"""Cherche les colonnes importables dans les titres (ligne 1) du fichier excel
|
||||
return: { idx : (field_name, convertor) }
|
||||
"""
|
||||
# log('adm_get_fields: titles=%s' % titles)
|
||||
Fmt = sco_import_format_dict()
|
||||
format_dict = sco_import_format_dict()
|
||||
fields = {}
|
||||
idx = 0
|
||||
for title in titles:
|
||||
title_n = adm_normalize_string(title)
|
||||
for k in Fmt:
|
||||
for v in Fmt[k]["aliases"]:
|
||||
for k in format_dict:
|
||||
for v in format_dict[k]["aliases"]:
|
||||
if adm_normalize_string(v) == title_n:
|
||||
typ = Fmt[k]["type"]
|
||||
typ = format_dict[k]["type"]
|
||||
if typ == "real":
|
||||
convertor = adm_convert_real
|
||||
elif typ == "integer" or typ == "int":
|
||||
@ -769,10 +769,9 @@ def adm_get_fields(titles, formsemestre_id):
|
||||
# doublons ?
|
||||
if k in [x[0] for x in fields.values()]:
|
||||
raise ScoFormatError(
|
||||
'scolars_import_admission: titre "%s" en double (ligne 1)'
|
||||
% (title),
|
||||
f"""scolars_import_admission: titre "{title}" en double (ligne 1)""",
|
||||
dest_url=url_for(
|
||||
"scolar.form_students_import_infos_admissions_apb",
|
||||
"scolar.form_students_import_infos_admissions",
|
||||
scodoc_dept=g.scodoc_dept,
|
||||
formsemestre_id=formsemestre_id,
|
||||
),
|
||||
|
@ -399,7 +399,7 @@ class releveBUT extends HTMLElement {
|
||||
<div>${module.titre} - ${evaluation.description || "Note"}</div>
|
||||
<div>
|
||||
${evaluation.note.value ?? "-"}
|
||||
<em>Coef. ${evaluation.coef}</em>
|
||||
<em>Coef. ${evaluation.coef ?? "*"}</em>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -450,7 +450,7 @@ class releveBUT extends HTMLElement {
|
||||
<div>${this.URL(evaluation.url, evaluation.description || "Évaluation")}</div>
|
||||
<div>
|
||||
${evaluation.note.value}
|
||||
<em>Coef. ${evaluation.coef}</em>
|
||||
<em>Coef. ${evaluation.coef ?? "*"}</em>
|
||||
</div>
|
||||
<div class=complement>
|
||||
<div>Coef</div><div>${evaluation.coef}</div>
|
||||
|
@ -265,7 +265,7 @@ def formsemestre_bulletinetud(
|
||||
):
|
||||
format = format or "html"
|
||||
|
||||
if not isinstance(formsemestre_id, int):
|
||||
if formsemestre_id is not None and not isinstance(formsemestre_id, int):
|
||||
raise ScoInvalidIdType(
|
||||
"formsemestre_bulletinetud: formsemestre_id must be an integer !"
|
||||
)
|
||||
@ -1775,7 +1775,7 @@ def evaluation_listenotes():
|
||||
if "moduleimpl_id" in vals and vals["moduleimpl_id"]:
|
||||
moduleimpl_id = int(vals["moduleimpl_id"])
|
||||
except ValueError as exc:
|
||||
raise ScoValueError("adresse invalide !") from exc
|
||||
raise ScoValueError("evaluation_listenotes: id invalides !") from exc
|
||||
|
||||
format = vals.get("format", "html")
|
||||
html_content, page_title = sco_liste_notes.do_evaluation_listenotes(
|
||||
|
Loading…
Reference in New Issue
Block a user