Merge pull request 'master' (#1) from ScoDoc/ScoDoc:master into master

Reviewed-on: lehmann/ScoDoc-Front#1
This commit is contained in:
Sébastien Lehmann 2021-12-19 18:36:06 +01:00
commit 19c736c894
20 changed files with 196 additions and 110 deletions

View File

@ -149,9 +149,9 @@ class ResultatsSemestreBUT:
"""dict synthèse résultats des modules indiqués,
avec évaluations de chacun."""
d = {}
etud_idx = self.etud_index[etud.id]
# etud_idx = self.etud_index[etud.id]
for mi in modimpls:
mod_idx = self.modimpl_coefs_df.columns.get_loc(mi.id)
# mod_idx = self.modimpl_coefs_df.columns.get_loc(mi.id)
# # moyennes indicatives (moyennes de moyennes d'UE)
# try:
# moyennes_etuds = np.nan_to_num(

View File

@ -111,13 +111,14 @@ def df_load_modimpl_notes(moduleimpl_id: int) -> tuple:
N'utilise pas de cache ScoDoc.
"""
# L'index du dataframe est la liste des étudiants inscrits au semestre, sans les démissionnaires
etudids = {
# L'index du dataframe est la liste des étudiants inscrits au semestre,
# sans les démissionnaires
etudids = [
e.etudid
for e in ModuleImpl.query.get(moduleimpl_id).formsemestre.get_inscrits(
include_dem=False
)
}
]
evaluations = Evaluation.query.filter_by(moduleimpl_id=moduleimpl_id).all()
# --- Calcul nombre d'inscrits pour détermnier si évaluation "complete":
if evaluations:
@ -128,7 +129,8 @@ def df_load_modimpl_notes(moduleimpl_id: int) -> tuple:
nb_inscrits_module = len(inscrits_module)
else:
nb_inscrits_module = 0
evals_notes = pd.DataFrame(index=etudids, dtype=float) # empty df with all students
# empty df with all students:
evals_notes = pd.DataFrame(index=etudids, dtype=float)
evaluations_completes = []
for evaluation in evaluations:
eval_df = pd.read_sql_query(

View File

@ -76,11 +76,11 @@ class Evaluation(db.Model):
db.session.add(copy)
return copy
def set_ue_poids(self, ue, poids: float):
def set_ue_poids(self, ue, poids: float) -> None:
"""Set poids évaluation vers cette UE"""
self.update_ue_poids_dict({ue.id: poids})
def set_ue_poids_dict(self, ue_poids_dict: dict):
def set_ue_poids_dict(self, ue_poids_dict: dict) -> None:
"""set poids vers les UE (remplace existants)
ue_poids_dict = { ue_id : poids }
"""
@ -91,16 +91,23 @@ class Evaluation(db.Model):
self.ue_poids = L
self.moduleimpl.invalidate_evaluations_poids() # inval cache
def update_ue_poids_dict(self, ue_poids_dict: dict):
def update_ue_poids_dict(self, ue_poids_dict: dict) -> None:
"""update poids vers UE (ajoute aux existants)"""
current = self.get_ue_poids_dict()
current.update(ue_poids_dict)
self.set_ue_poids_dict(current)
def get_ue_poids_dict(self):
def get_ue_poids_dict(self) -> dict:
"""returns { ue_id : poids }"""
return {p.ue.id: p.poids for p in self.ue_poids}
def get_ue_poids_str(self) -> str:
"""string describing poids, for excel cells and pdfs
Note: si les poids ne sont pas initialisés (poids par défaut),
ils ne sont pas affichés.
"""
return ", ".join([f"{p.ue.acronyme}: {p.poids}" for p in self.ue_poids])
class EvaluationUEPoids(db.Model):
"""Poids des évaluations (BUT)

View File

@ -33,6 +33,7 @@ import json
from app.but import bulletin_but
from app.models.formsemestre import FormSemestre
from app.models.etudiants import Identite
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
@ -86,6 +87,7 @@ def formsemestre_bulletinetud_published_dict(
from app.scodoc import sco_bulletins
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
etud = Identite.query.get(etudid)
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
if formsemestre.formation.is_apc():
@ -139,6 +141,11 @@ def formsemestre_bulletinetud_published_dict(
if not published:
return d # stop !
etat_inscription = etud.etat_inscription(formsemestre.id)
if etat_inscription != scu.INSCRIT:
d.update(dict_decision_jury(etudid, formsemestre_id, with_decisions=True))
return d
# Groupes:
partitions = sco_groups.get_partitions_list(formsemestre_id, with_default=False)
partitions_etud_groups = {} # { partition_id : { etudid : group } }

View File

@ -104,7 +104,10 @@ def do_ue_create(args):
# check duplicates
ues = ue_list({"formation_id": args["formation_id"], "acronyme": args["acronyme"]})
if ues:
raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"])
raise ScoValueError(
f"""Acronyme d'UE "{args['acronyme']}" déjà utilisé !
(chaque UE doit avoir un acronyme unique dans la formation)"""
)
# create
ue_id = _ueEditor.create(cnx, args)
@ -471,7 +474,7 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): # was ue_list
raise ScoValueError("invalid formation_id")
parcours = formation.get_parcours()
is_apc = parcours.APC_SAE
locked = sco_formations.formation_has_locked_sems(formation_id)
locked = formation.has_locked_sems()
if semestre_idx == "all":
semestre_idx = None
else:
@ -541,7 +544,7 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): # was ue_list
if locked:
H.append(
f"""<p class="help">Cette formation est verrouillée car
{len(locked)} semestres verrouillés s'y réferent.
des semestres verrouillés s'y réferent.
Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module),
vous devez:
</p>
@ -1146,7 +1149,10 @@ def do_ue_edit(args, bypass_lock=False, dont_invalidate_cache=False):
new_acro = args["acronyme"]
ues = ue_list({"formation_id": ue["formation_id"], "acronyme": new_acro})
if ues and ues[0]["ue_id"] != ue_id:
raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"])
raise ScoValueError(
f"""Acronyme d'UE "{args['acronyme']}" déjà utilisé !
(chaque UE doit avoir un acronyme unique dans la formation)"""
)
# On ne peut pas supprimer le code UE:
if "ue_code" in args and not args["ue_code"]:

View File

@ -109,30 +109,10 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
nb_inscrits = len(
sco_groups.do_evaluation_listeetuds_groups(evaluation_id, getallstudents=True)
)
NotesDB = sco_evaluation_db.do_evaluation_get_all_notes(
etuds_notes_dict = sco_evaluation_db.do_evaluation_get_all_notes(
evaluation_id
) # { etudid : value }
notes = [x["value"] for x in NotesDB.values()]
nb_abs = len([x for x in notes if x is None])
nb_neutre = len([x for x in notes if x == scu.NOTES_NEUTRALISE])
nb_att = len([x for x in notes if x == scu.NOTES_ATTENTE])
moy_num, median_num, mini_num, maxi_num = notes_moyenne_median_mini_maxi(notes)
if moy_num is None:
median, moy = "", ""
median_num, moy_num = None, None
mini, maxi = "", ""
mini_num, maxi_num = None, None
else:
median = scu.fmt_note(median_num)
moy = scu.fmt_note(moy_num)
mini = scu.fmt_note(mini_num)
maxi = scu.fmt_note(maxi_num)
# cherche date derniere modif note
if len(NotesDB):
t = [x["date"] for x in NotesDB.values()]
last_modif = max(t)
else:
last_modif = None
) # { etudid : note }
# ---- Liste des groupes complets et incomplets
E = sco_evaluation_db.do_evaluation_list(args={"evaluation_id": evaluation_id})[0]
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
@ -163,8 +143,32 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
# Nombre de notes valides d'étudiants inscrits au module
# (car il peut y avoir des notes d'étudiants désinscrits depuis l'évaluation)
nb_notes = len(insmodset.intersection(NotesDB))
nb_notes_total = len(NotesDB)
etudids_avec_note = insmodset.intersection(etuds_notes_dict)
nb_notes = len(etudids_avec_note)
# toutes saisies, y compris chez des non-inscrits:
nb_notes_total = len(etuds_notes_dict)
notes = [etuds_notes_dict[etudid]["value"] for etudid in etudids_avec_note]
nb_abs = len([x for x in notes if x is None])
nb_neutre = len([x for x in notes if x == scu.NOTES_NEUTRALISE])
nb_att = len([x for x in notes if x == scu.NOTES_ATTENTE])
moy_num, median_num, mini_num, maxi_num = notes_moyenne_median_mini_maxi(notes)
if moy_num is None:
median, moy = "", ""
median_num, moy_num = None, None
mini, maxi = "", ""
mini_num, maxi_num = None, None
else:
median = scu.fmt_note(median_num)
moy = scu.fmt_note(moy_num)
mini = scu.fmt_note(mini_num)
maxi = scu.fmt_note(maxi_num)
# cherche date derniere modif note
if len(etuds_notes_dict):
t = [x["date"] for x in etuds_notes_dict.values()]
last_modif = max(t)
else:
last_modif = None
# On considere une note "manquante" lorsqu'elle n'existe pas
# ou qu'elle est en attente (ATT)
@ -181,8 +185,8 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
groups[group["group_id"]] = group
#
isMissing = False
if i["etudid"] in NotesDB:
val = NotesDB[i["etudid"]]["value"]
if i["etudid"] in etuds_notes_dict:
val = etuds_notes_dict[i["etudid"]]["value"]
if val == scu.NOTES_ATTENTE:
isMissing = True
TotalNbAtt += 1

View File

@ -230,9 +230,10 @@ def formation_import_xml(doc: str, import_tags=True):
ue_id = sco_edit_ue.do_ue_create(ue_info[1])
if xml_ue_id:
ues_old2new[xml_ue_id] = ue_id
ue_reference = int(ue_info[1].get("reference"))
# élément optionnel présent dans les exports BUT:
ue_reference = ue_info[1].get("reference")
if ue_reference:
ue_reference_to_id[ue_reference] = ue_id
ue_reference_to_id[int(ue_reference)] = ue_id
# -- create matieres
for mat_info in ue_info[2]:
assert mat_info[0] == "matiere"

View File

@ -66,7 +66,9 @@ def do_formsemestre_inscription_list(*args, **kw):
def do_formsemestre_inscription_listinscrits(formsemestre_id):
"""Liste les inscrits (état I) à ce semestre et cache le résultat"""
"""Liste les inscrits (état I) à ce semestre et cache le résultat.
Result: [ { "etudid":, "formsemestre_id": , "etat": , "etape": }]
"""
r = sco_cache.SemInscriptionsCache.get(formsemestre_id)
if r is None:
# retreive list

View File

@ -1210,6 +1210,7 @@ def formsemestre_tableau_modules(
)
if mod.module_type in (
None, # ne devrait pas être nécessaire car la migration a remplacé les NULLs
ModuleType.STANDARD,
ModuleType.RESSOURCE,
ModuleType.SAE,
@ -1249,7 +1250,7 @@ def formsemestre_tableau_modules(
% (modimpl["moduleimpl_id"], nb_malus_notes)
)
else:
raise ValueError("Invalid module_type") # a bug
raise ValueError(f"Invalid module_type {mod.module_type}") # a bug
H.append("</td></tr>")
return "\n".join(H)

View File

@ -35,7 +35,6 @@ Optimisation possible:
"""
import collections
import operator
import re
import time
from xml.etree import ElementTree
@ -45,6 +44,7 @@ import flask
from flask import g, request
from flask import url_for, make_response
from app import db
from app.models.groups import Partition
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb

View File

@ -32,6 +32,7 @@ import flask
from flask import url_for, g, request
from app import models
from app.models.evaluations import Evaluation
from app.models.moduleimpls import ModuleImpl
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
@ -53,35 +54,34 @@ from app.scodoc.gen_tables import GenTable
from app.scodoc.htmlutils import histogram_notes
def do_evaluation_listenotes():
def do_evaluation_listenotes(
evaluation_id=None, moduleimpl_id=None, format="html"
) -> str:
"""
Affichage des notes d'une évaluation
args: evaluation_id ou moduleimpl_id
(si moduleimpl_id, affiche toutes les évaluations du module)
Affichage des notes d'une évaluation (si evaluation_id)
ou de toutes les évaluations d'un module (si moduleimpl_id)
"""
mode = None
vals = scu.get_request_args()
if "evaluation_id" in vals:
evaluation_id = int(vals["evaluation_id"])
mode = "eval"
evals = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id})
if "moduleimpl_id" in vals and vals["moduleimpl_id"]:
moduleimpl_id = int(vals["moduleimpl_id"])
if moduleimpl_id:
mode = "module"
evals = sco_evaluation_db.do_evaluation_list({"moduleimpl_id": moduleimpl_id})
if not mode:
elif evaluation_id:
mode = "eval"
evals = sco_evaluation_db.do_evaluation_list({"evaluation_id": evaluation_id})
else:
raise ValueError("missing argument: evaluation or module")
if not evals:
return "<p>Aucune évaluation !</p>"
format = vals.get("format", "html")
E = evals[0] # il y a au moins une evaluation
modimpl = ModuleImpl.query.get(E["moduleimpl_id"])
# description de l'evaluation
if mode == "eval":
H = [sco_evaluations.evaluation_describe(evaluation_id=evaluation_id)]
page_title = f"Notes {E['description'] or modimpl.module.code}"
else:
H = []
page_title = f"Notes {modimpl.module.code}"
# groupes
groups = sco_groups.do_evaluation_listegroupes(
E["evaluation_id"], include_default=True
@ -187,7 +187,7 @@ def do_evaluation_listenotes():
is_submitted=True, # toujours "soumis" (démarre avec liste complète)
)
if tf[0] == 0:
return "\n".join(H) + "\n" + tf[1]
return "\n".join(H) + "\n" + tf[1], page_title
elif tf[0] == -1:
return flask.redirect(
"%s/Notes/moduleimpl_status?moduleimpl_id=%s"
@ -198,16 +198,19 @@ def do_evaluation_listenotes():
note_sur_20 = tf[2]["note_sur_20"]
hide_groups = tf[2]["hide_groups"]
with_emails = tf[2]["with_emails"]
return _make_table_notes(
tf[1],
evals,
format=format,
note_sur_20=note_sur_20,
anonymous_listing=anonymous_listing,
group_ids=tf[2]["group_ids"],
hide_groups=hide_groups,
with_emails=with_emails,
mode=mode,
return (
_make_table_notes(
tf[1],
evals,
format=format,
note_sur_20=note_sur_20,
anonymous_listing=anonymous_listing,
group_ids=tf[2]["group_ids"],
hide_groups=hide_groups,
with_emails=with_emails,
mode=mode,
),
page_title,
)
@ -393,6 +396,7 @@ def _make_table_notes(
key_mgr,
note_sur_20,
keep_numeric,
format=format,
)
columns_ids.append(e["evaluation_id"])
#
@ -406,7 +410,7 @@ def _make_table_notes(
# Si module, ajoute la (les) "moyenne(s) du module:
if mode == "module":
if len(evals) > 1:
# Moyenne de l'étudant dans le module
# Moyenne de l'étudiant dans le module
# Affichée même en APC à titre indicatif
_add_moymod_column(
sem["formsemestre_id"],
@ -635,6 +639,7 @@ def _add_eval_columns(
K,
note_sur_20,
keep_numeric,
format="html",
):
"""Add eval e"""
nb_notes = 0
@ -643,6 +648,7 @@ def _add_eval_columns(
sum_notes = 0
notes = [] # liste des notes numeriques, pour calcul histogramme uniquement
evaluation_id = e["evaluation_id"]
e_o = Evaluation.query.get(evaluation_id) # XXX en attendant ré-écriture
NotesDB = sco_evaluation_db.do_evaluation_get_all_notes(evaluation_id)
for row in rows:
etudid = row["etudid"]
@ -704,9 +710,12 @@ def _add_eval_columns(
row_coefs[evaluation_id] = "coef. %s" % e["coefficient"]
if is_apc:
row_poids[evaluation_id] = _mini_table_eval_ue_poids(
evaluation_id, evals_poids, ues
)
if format == "html":
row_poids[evaluation_id] = _mini_table_eval_ue_poids(
evaluation_id, evals_poids, ues
)
else:
row_poids[evaluation_id] = e_o.get_ue_poids_str()
if note_sur_20:
nmax = 20.0
else:

View File

@ -31,9 +31,10 @@ import time
from flask import g, url_for
from flask_login import current_user
from app.auth.models import User
from app.auth.models import User
from app.models import ModuleImpl
from app.models.evaluations import Evaluation
import app.scodoc.sco_utils as scu
from app.scodoc.sco_permissions import Permission
@ -391,8 +392,9 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
)
H.append("""<table class="moduleimpl_evaluations">""")
eval_index = len(mod_evals) - 1
first = True
first_eval = True
for eval in mod_evals:
evaluation = Evaluation.query.get(eval["evaluation_id"]) # TODO unifier
etat = sco_evaluations.do_evaluation_etat(
eval["evaluation_id"],
partition_id=partition_id,
@ -406,9 +408,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
else:
tr_class = "mievr"
tr_class_1 = "mievr"
if first:
first = False
else:
if not first_eval:
H.append("""<tr><td colspan="8">&nbsp;</td></tr>""")
tr_class_1 += " mievr_spaced"
H.append("""<tr class="%s"><td class="mievr_tit" colspan="8">""" % tr_class_1)
@ -586,19 +586,35 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
H.append("""</td></tr>""")
#
if etat["nb_notes"] == 0:
H.append("""<tr class="%s"><td colspan="8">&nbsp;""" % tr_class)
H.append("""</td></tr>""")
H.append("""<tr class="%s"><td></td>""" % tr_class)
if modimpl.module.is_apc():
H.append(
f"""<td colspan="7" class="eval_poids">{
evaluation.get_ue_poids_str()}</td>"""
)
else:
H.append('<td colspan="7"></td>')
H.append("""</tr>""")
else: # il y a deja des notes saisies
gr_moyennes = etat["gr_moyennes"]
first_group = True
for gr_moyenne in gr_moyennes:
H.append("""<tr class="%s">""" % tr_class)
H.append("""<td colspan="2">&nbsp;</td>""")
H.append("""<td>&nbsp;</td>""")
if first_group and modimpl.module.is_apc():
H.append(
f"""<td class="eval_poids" colspan="3">{
evaluation.get_ue_poids_str()}</td>"""
)
else:
H.append("""<td colspan="3"></td>""")
first_group = False
if gr_moyenne["group_name"] is None:
name = "Tous" # tous
else:
name = "Groupe %s" % gr_moyenne["group_name"]
H.append(
"""<td colspan="5" class="mievr_grtit">%s &nbsp;</td><td>""" % name
"""<td colspan="3" class="mievr_grtit">%s &nbsp;</td><td>""" % name
)
if gr_moyenne["gr_nb_notes"] > 0:
H.append("%(gr_moy)s" % gr_moyenne)
@ -637,6 +653,7 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
H.append("""</a>""")
H.append("</span>")
H.append("""</td></tr>""")
first_eval = False
#
if caneditevals or not sem["etat"]:

View File

@ -37,7 +37,8 @@ from flask import make_response
from app import log
from app.but import bulletin_but
from app.models import FormSemestre, UniteEns, Module, ModuleImpl
from app.models import FormSemestre
from app.models.etudiants import Identite
import app.scodoc.sco_utils as scu
from app.scodoc import html_sco_header
@ -937,6 +938,9 @@ def _formsemestre_recapcomplet_json(
:param force_publishing: donne les bulletins même si non "publiés sur portail"
:returns: dict, "", "json"
"""
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
is_apc = formsemestre.formation.is_apc()
if xml_nodate:
docdate = ""
else:
@ -958,14 +962,18 @@ def _formsemestre_recapcomplet_json(
T = nt.get_table_moyennes_triees()
for t in T:
etudid = t[-1]
bulletins.append(
sco_bulletins_json.formsemestre_bulletinetud_published_dict(
if is_apc:
etud = Identite.query.get(etudid)
r = bulletin_but.ResultatsSemestreBUT(formsemestre)
bul = r.bulletin_etud(etud, formsemestre)
else:
bul = sco_bulletins_json.formsemestre_bulletinetud_published_dict(
formsemestre_id,
etudid,
force_publishing=force_publishing,
xml_with_decisions=xml_with_decisions,
)
)
bulletins.append(bul)
return J, "", "json"

View File

@ -408,7 +408,7 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False):
if not dialog_confirmed:
nb_changed, nb_suppress, existing_decisions = notes_add(
current_user, evaluation_id, notes, do_it=False
current_user, evaluation_id, notes, do_it=False, check_inscription=False
)
msg = (
"<p>Confirmer la suppression des %d notes ? <em>(peut affecter plusieurs groupes)</em></p>"
@ -426,7 +426,11 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False):
# modif
nb_changed, nb_suppress, existing_decisions = notes_add(
current_user, evaluation_id, notes, comment="effacer tout"
current_user,
evaluation_id,
notes,
comment="effacer tout",
check_inscription=False,
)
assert nb_changed == nb_suppress
H = ["<p>%s notes supprimées</p>" % nb_suppress]
@ -454,7 +458,14 @@ def evaluation_suppress_alln(evaluation_id, dialog_confirmed=False):
return html_sco_header.sco_header() + "\n".join(H) + html_sco_header.sco_footer()
def notes_add(user, evaluation_id: int, notes: list, comment=None, do_it=True) -> tuple:
def notes_add(
user,
evaluation_id: int,
notes: list,
comment=None,
do_it=True,
check_inscription=True,
) -> tuple:
"""
Insert or update notes
notes is a list of tuples (etudid,value)
@ -475,7 +486,7 @@ def notes_add(user, evaluation_id: int, notes: list, comment=None, do_it=True) -
)
}
for (etudid, value) in notes:
if etudid not in inscrits:
if check_inscription and (etudid not in inscrits):
raise NoteProcessError("etudiant non inscrit dans ce module")
if not ((value is None) or (type(value) == type(1.0))):
raise NoteProcessError(

View File

@ -16,7 +16,7 @@ main{
--couleurPrincipale: rgb(240,250,255);
--couleurFondTitresUE: rgb(206,255,235);
--couleurFondTitresRes: rgb(125, 170, 255);
--couleurFondTitresSAE: rgb(255, 190, 69);
--couleurFondTitresSAE: rgb(211, 255, 255);
--couleurSecondaire: #fec;
--couleurIntense: #c09;
--couleurSurlignage: rgba(232, 255, 132, 0.47);

View File

@ -1476,6 +1476,9 @@ span.evalindex {
margin-left: 3px;
}
table.moduleimpl_evaluations td.eval_poids {
color:rgb(0, 0, 255);
}
/* Formulaire edition des partitions */
form#editpart table {

View File

@ -12,7 +12,7 @@
{% endblock %}
{% block title %}
{% if title %}{{ title }} - ScoDoc{% else %}Welcome to ScoDoc{% endif %}
{% if title %}{{ title }} - ScoDoc{% else %}ScoDoc{% endif %}
{% endblock %}
{% block content %}
@ -31,9 +31,9 @@
{% endwith %}
</div>
{% if sco.sem %}
{% block formsemestre_header %}
{% include "formsemestre_header.html" %}
{% endblock %}
{% block formsemestre_header %}
{% include "formsemestre_header.html" %}
{% endblock %}
{% endif %}
{% block app_content %}

View File

@ -285,6 +285,8 @@ def formsemestre_bulletinetud(
prefer_mail_perso=False,
code_nip=None,
):
if not formsemestre_id:
flask.abort(404, "argument manquant: formsemestre_id")
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
if formsemestre.formation.is_apc() and format != "oldjson":
if etudid:
@ -299,7 +301,7 @@ def formsemestre_bulletinetud(
elif format == "html":
return render_template(
"but/bulletin.html",
title="Bulletin BUT",
title=f"Bul. {etud.nom} - BUT",
bul_url=url_for(
"notes.formsemestre_bulletinetud",
scodoc_dept=g.scodoc_dept,
@ -1726,27 +1728,33 @@ def evaluation_create(moduleimpl_id):
@scodoc7func
def evaluation_listenotes():
"""Affichage des notes d'une évaluation"""
if request.args.get("format", "html") == "html":
evaluation_id = None
moduleimpl_id = None
vals = scu.get_request_args()
if "evaluation_id" in vals:
evaluation_id = int(vals["evaluation_id"])
mode = "eval"
if "moduleimpl_id" in vals and vals["moduleimpl_id"]:
moduleimpl_id = int(vals["moduleimpl_id"])
mode = "module"
format = vals.get("format", "html")
B, page_title = sco_liste_notes.do_evaluation_listenotes(
evaluation_id=evaluation_id, moduleimpl_id=moduleimpl_id, format=format
)
if format == "html":
H = html_sco_header.sco_header(
page_title=page_title,
cssstyles=["css/verticalhisto.css"],
javascripts=["js/etud_info.js"],
init_qtip=True,
)
F = html_sco_header.sco_footer()
else:
H, F = "", ""
B = sco_liste_notes.do_evaluation_listenotes()
if H:
return H + B + F
else:
return B
sco_publish(
"/do_evaluation_listenotes",
sco_liste_notes.do_evaluation_listenotes,
Permission.ScoView,
)
sco_publish(
"/evaluation_list_operations",
sco_undo_notes.evaluation_list_operations,

View File

@ -1,7 +1,7 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
SCOVERSION = "9.1.10"
SCOVERSION = "9.1.11"
SCONAME = "ScoDoc"

View File

@ -1,4 +1,4 @@
# -*- coding: UTF-8 -*
# -*- coding: UTF-8 -*-
"""Application Flask: ScoDoc