Nouvelle table recap avec malus.

This commit is contained in:
Emmanuel Viennet 2023-02-02 14:27:15 -03:00
parent b3839dd8fb
commit 79c4a23ab9
6 changed files with 80 additions and 38 deletions

View File

@ -17,8 +17,9 @@ from app.comp.bonus_spo import BonusSport
from app.models import ScoDocSiteConfig from app.models import ScoDocSiteConfig
from app.models.moduleimpls import ModuleImpl from app.models.moduleimpls import ModuleImpl
from app.models.ues import DispenseUE, UniteEns from app.models.ues import DispenseUE, UniteEns
from app.scodoc.sco_codes_parcours import UE_SPORT
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc.sco_codes_parcours import UE_SPORT
from app.scodoc.sco_utils import ModuleType
class ResultatsSemestreBUT(NotesTableCompat): class ResultatsSemestreBUT(NotesTableCompat):
@ -185,9 +186,15 @@ class ResultatsSemestreBUT(NotesTableCompat):
modimpls = [ modimpls = [
modimpl modimpl
for modimpl in self.formsemestre.modimpls_sorted for modimpl in self.formsemestre.modimpls_sorted
if modimpl.module.ue.type != UE_SPORT if (
and (coefs[modimpl.id][ue.id] != 0) modimpl.module.ue.type != UE_SPORT
and self.modimpl_inscr_df[modimpl.id][etudid] and (coefs[modimpl.id][ue.id] != 0)
and self.modimpl_inscr_df[modimpl.id][etudid]
)
or (
modimpl.module.module_type == ModuleType.MALUS
and modimpl.module.ue_id == ue.id
)
] ]
if not with_bonus: if not with_bonus:
return [ return [

View File

@ -667,7 +667,7 @@ class ResultatsSemestre(ResultatsCache):
"ues_validables", "ues_validables",
"UEs", "UEs",
ue_valid_txt_html, ue_valid_txt_html,
"col_ues_validables", group="col_ues_validables",
classes=classes, classes=classes,
raw_content=ue_valid_txt, raw_content=ue_valid_txt,
data={"order": row.nb_ues_validables}, # tri data={"order": row.nb_ues_validables}, # tri
@ -719,7 +719,7 @@ class ResultatsSemestre(ResultatsCache):
ue.acronyme, ue.acronyme,
table.fmt_note(val), table.fmt_note(val),
group=f"col_ue_{ue.id}", group=f"col_ue_{ue.id}",
classes=["col_ue", note_class], classes=["col_ue", "col_moy_ue", note_class],
) )
row.table.foot_title_row.cells[col_id].target_attrs[ row.table.foot_title_row.cells[col_id].target_attrs[
"title" "title"
@ -751,7 +751,11 @@ class ResultatsSemestre(ResultatsCache):
col_id = f"moy_{modimpl.module.type_abbrv()}_{modimpl.id}_{ue.id}" col_id = f"moy_{modimpl.module.type_abbrv()}_{modimpl.id}_{ue.id}"
val_fmt = val_fmt_html = table.fmt_note(val) val_fmt = val_fmt_html = table.fmt_note(val)
if modimpl.module.module_type == scu.ModuleType.MALUS: if modimpl.module.module_type == scu.ModuleType.MALUS:
val_fmt_html = (scu.EMO_RED_TRIANGLE_DOWN + val_fmt) if val else "" val_fmt_html = (
(scu.EMO_RED_TRIANGLE_DOWN + val_fmt)
if val and not np.isnan(val)
else ""
)
cell = row.add_cell( cell = row.add_cell(
col_id, col_id,
modimpl.module.code, modimpl.module.code,
@ -992,22 +996,7 @@ class ResultatsSemestre(ResultatsCache):
) )
first_partition = True first_partition = True
for partition in partitions: for partition in partitions:
col_classes = [] # la classe "partition" sera ajoutée par la table
if not first_partition:
col_classes.append("partition_aux")
first_partition = False
cid = f"part_{partition['partition_id']}" cid = f"part_{partition['partition_id']}"
cell_head, cell_foot = table.add_title(cid, partition["partition_name"])
cell_head.classes += col_classes
cell_foot.classes += col_classes
if partition["bul_show_rank"]:
rg_cid = cid + "_rg" # rang dans la partition
cell_head, cell_foot = table.add_title(
cid, f"Rg {partition['partition_name']}"
)
cell_head.classes.append("partition_rangs")
cell_foot.classes.append("partition_rangs")
partition_etud_groups = partitions_etud_groups[partition["partition_id"]] partition_etud_groups = partitions_etud_groups[partition["partition_id"]]
for row in table.rows: for row in table.rows:
@ -1030,9 +1019,12 @@ class ResultatsSemestre(ResultatsCache):
cid, cid,
partition["partition_name"], partition["partition_name"],
gr_name, gr_name,
"partition", group="partition",
classes=col_classes, classes=[] if first_partition else ["partition_aux"],
# la classe "partition" est ajoutée par la Table car c'est le group
# la classe "partition_aux" est ajoutée à partir de la 2eme partition affichée
) )
first_partition = False
# Rangs dans groupe # Rangs dans groupe
if ( if (
@ -1041,7 +1033,14 @@ class ResultatsSemestre(ResultatsCache):
and (group["id"] in self.moy_gen_rangs_by_group) and (group["id"] in self.moy_gen_rangs_by_group)
): ):
rang = self.moy_gen_rangs_by_group[group["id"]][0] rang = self.moy_gen_rangs_by_group[group["id"]][0]
row.add_cell(rg_cid, None, rang.get(etudid, ""), "partition") rg_cid = cid + "_rg" # rang dans la partition
row.add_cell(
rg_cid,
f"Rg {partition['partition_name']}",
rang.get(etudid, ""),
group="partition",
classes=["partition_aux"],
)
def _recap_add_evaluations(self, table: tb.Table): def _recap_add_evaluations(self, table: tb.Table):
"""Ajoute les colonnes avec les notes aux évaluations """Ajoute les colonnes avec les notes aux évaluations

View File

@ -4,8 +4,6 @@
""" """
from app import db from app import db
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
@ -53,6 +51,13 @@ class NotesNotes(db.Model):
d.pop("_sa_instance_state", None) d.pop("_sa_instance_state", None)
return d return d
def __repr__(self):
"pour debug"
from app.models.evaluations import Evaluation
return f"""<{self.__class__.__name__} {self.id} v={self.value} {self.date.isoformat()
} {Evaluation.query.get(self.evaluation_id) if self.evaluation_id else "X" }>"""
class NotesNotesLog(db.Model): class NotesNotesLog(db.Model):
"""Historique des modifs sur notes (anciennes entrees de notes_notes)""" """Historique des modifs sur notes (anciennes entrees de notes_notes)"""

View File

@ -1223,6 +1223,7 @@ def partition_move(partition_id, after=0, redirect=1):
partition["numero"], neigh["numero"] = neigh["numero"], partition["numero"] partition["numero"], neigh["numero"] = neigh["numero"], partition["numero"]
partitionEditor.edit(cnx, partition) partitionEditor.edit(cnx, partition)
partitionEditor.edit(cnx, neigh) partitionEditor.edit(cnx, neigh)
sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre_id)
# redirect to partition edit page: # redirect to partition edit page:
if redirect: if redirect:
@ -1297,7 +1298,7 @@ def partition_set_name(partition_id, partition_name, redirect=1):
) )
if len(r) > 1 or (len(r) == 1 and r[0]["id"] != partition_id): if len(r) > 1 or (len(r) == 1 and r[0]["id"] != partition_id):
raise ScoValueError( raise ScoValueError(
"Partition %s déjà existante dans ce semestre !" % partition_name f"Partition {partition_name} déjà existante dans ce semestre !"
) )
if not sco_permissions_check.can_change_groups(formsemestre_id): if not sco_permissions_check.can_change_groups(formsemestre_id):
@ -1307,6 +1308,7 @@ def partition_set_name(partition_id, partition_name, redirect=1):
partitionEditor.edit( partitionEditor.edit(
cnx, {"partition_id": partition_id, "partition_name": partition_name} cnx, {"partition_id": partition_id, "partition_name": partition_name}
) )
sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre_id)
# redirect to partition edit page: # redirect to partition edit page:
if redirect: if redirect:
@ -1339,6 +1341,7 @@ def group_set_name(group: GroupDescr, group_name: str, redirect=True):
group.group_name = group_name group.group_name = group_name
db.session.add(group) db.session.add(group)
db.session.commit() db.session.commit()
sco_cache.invalidate_formsemestre(formsemestre_id=group.partition.formsemestre_id)
# redirect to partition edit page: # redirect to partition edit page:
if redirect: if redirect:
@ -1396,8 +1399,6 @@ def groups_auto_repartition(partition_id=None):
"""Reparti les etudiants dans des groupes dans une partition, en respectant le niveau """Reparti les etudiants dans des groupes dans une partition, en respectant le niveau
et la mixité. et la mixité.
""" """
from app.scodoc import sco_formsemestre
partition = get_partition(partition_id) partition = get_partition(partition_id)
if not partition["groups_editable"]: if not partition["groups_editable"]:
raise AccessDenied("Partition non éditable") raise AccessDenied("Partition non éditable")

View File

@ -227,7 +227,11 @@ class Table(Element):
if col_id not in self.titles: if col_id not in self.titles:
self.titles[col_id] = title self.titles[col_id] = title
self.head_title_row.cells[col_id] = self.head_title_row.add_cell( self.head_title_row.cells[col_id] = self.head_title_row.add_cell(
col_id, None, title, classes=classes col_id,
None,
title,
classes=classes,
group=self.column_group.get(col_id),
) )
self.foot_title_row.cells[col_id] = self.foot_title_row.add_cell( self.foot_title_row.cells[col_id] = self.foot_title_row.add_cell(
col_id, None, title, classes=classes col_id, None, title, classes=classes
@ -276,9 +280,14 @@ class Row(Element):
group: groupe de colonnes group: groupe de colonnes
classes is a list of css class names classes is a list of css class names
""" """
if (classes is None) or (group not in classes):
# ajoute le nom de groupe aux classes
classes = [group or ""] + (classes or [])
else:
classes = classes.copy()
cell = Cell( cell = Cell(
content, content,
(classes or []) + [group or ""], # ajoute le nom de groupe aux classes classes,
elt=elt or self.cell_elt, elt=elt or self.cell_elt,
attrs=attrs, attrs=attrs,
data=data, data=data,
@ -294,7 +303,7 @@ class Row(Element):
"""Add a cell to the row. """Add a cell to the row.
Si title est None, il doit avoir été ajouté avec table.add_title(). Si title est None, il doit avoir été ajouté avec table.add_title().
""" """
cell.data["group"] = column_group cell.data["group"] = column_group or ""
self.cells[col_id] = cell self.cells[col_id] = cell
if col_id not in self.table.column_ids: if col_id not in self.table.column_ids:
self.table.column_ids.append(col_id) self.table.column_ids.append(col_id)
@ -375,7 +384,7 @@ class Cell(Element):
if self.elt == "th": if self.elt == "th":
self.attrs["scope"] = "row" self.attrs["scope"] = "row"
self.data = data or {} self.data = data.copy() if data else {}
self.raw_content = raw_content or content self.raw_content = raw_content or content
self.target = target self.target = target
self.target_attrs = target_attrs or {} self.target_attrs = target_attrs or {}

View File

@ -1,7 +1,11 @@
// Tableau recap notes // Tableau recap notes
$(function () { $(function () {
$(function () { $(function () {
let hidden_colums = ["etud_codes", "identite_detail", "partition_aux", "partition_rangs", "admission", "col_empty"]; let hidden_colums = [
"etud_codes", "identite_detail",
"partition_aux", "partition_rangs", "admission",
"col_empty"
];
let mode_jury_but_bilan = $('table.table_recap').hasClass("table_jury_but_bilan"); let mode_jury_but_bilan = $('table.table_recap').hasClass("table_jury_but_bilan");
if (mode_jury_but_bilan) { if (mode_jury_but_bilan) {
// table bilan décisions: cache les notes // table bilan décisions: cache les notes
@ -30,6 +34,7 @@ $(function () {
// Les colonnes visibles étant mémorisé, il faut initialiser les titres des boutons // Les colonnes visibles étant mémorisé, il faut initialiser les titres des boutons
function update_buttons_labels(dt) { function update_buttons_labels(dt) {
console.log("update_buttons_labels");
dt.buttons('toggle_ident:name').text(dt.columns(".identite_detail").visible()[0] ? "Nom seul" : "Civ/Nom/Prénom"); dt.buttons('toggle_ident:name').text(dt.columns(".identite_detail").visible()[0] ? "Nom seul" : "Civ/Nom/Prénom");
dt.buttons('toggle_partitions:name').text(dt.columns(".partition_aux").visible()[0] ? "Cacher les groupes" : "Montrer groupes"); dt.buttons('toggle_partitions:name').text(dt.columns(".partition_aux").visible()[0] ? "Cacher les groupes" : "Montrer groupes");
if (!$('table.table_recap').hasClass("table_jury_but")) { if (!$('table.table_recap').hasClass("table_jury_but")) {
@ -106,7 +111,7 @@ $(function () {
$('table.table_recap').hasClass("apc") ? $('table.table_recap').hasClass("apc") ?
{ {
name: "toggle_res", name: "toggle_res",
text: "Visilité ressources", text: "Visibilité ressources",
action: function (e, dt, node, config) { action: function (e, dt, node, config) {
let visible = dt.columns(".col_res").visible()[0]; let visible = dt.columns(".col_res").visible()[0];
dt.columns(".col_res").visible(!visible); dt.columns(".col_res").visible(!visible);
@ -159,6 +164,14 @@ $(function () {
} }
}); });
} }
buttons.push({
name: "reset_table_display",
text: "Rétablir affichage par défaut",
action: function (e, dt, node, config) {
localStorage.clear();
location.reload();
}
});
try { try {
let table = $('table.table_recap').DataTable( let table = $('table.table_recap').DataTable(
{ {
@ -182,7 +195,7 @@ $(function () {
}, },
{ {
// Elimine les 0 à gauche pour les exports excel et les "copy" // Elimine les 0 à gauche pour les exports excel et les "copy"
targets: ["col_mod", "col_moy_gen", "col_ue", "col_res", "col_sae", "evaluation", "col_rcue"], targets: ["col_mod", "col_moy_gen", "col_moy_ue", "col_res", "col_sae", "evaluation", "col_rcue"],
render: function (data, type, row) { render: function (data, type, row) {
return type === 'export' ? data.replace(/0(\d\..*)/, '$1') : data; return type === 'export' ? data.replace(/0(\d\..*)/, '$1') : data;
} }
@ -194,6 +207,14 @@ $(function () {
return type === 'export' ? data.replace(/.*(\d\d\.\d\d)/, '$1').replace(/0(\d\..*)/, '$1') : data; return type === 'export' ? data.replace(/.*(\d\d\.\d\d)/, '$1').replace(/0(\d\..*)/, '$1') : data;
} }
}, },
{
// Elimine emoji warning sur UEs
targets: ["col_ues_validables"],
render: function (data, type, row) {
return type === 'export' ? data.replace(/(\d+\/\d+).*/, '$1') : data;
}
}
], ],
dom: 'Bfrtip', dom: 'Bfrtip',
buttons: [ buttons: [
@ -235,6 +256,7 @@ $(function () {
"order": order_info, "order": order_info,
} }
); );
update_buttons_labels(table);
} catch (error) { } catch (error) {
// l'erreur peut etre causee par un ancien storage: // l'erreur peut etre causee par un ancien storage:
localStorage.removeItem(etudids_key); localStorage.removeItem(etudids_key);
@ -242,7 +264,6 @@ $(function () {
localStorage.removeItem(order_info_key); localStorage.removeItem(order_info_key);
location.reload(); location.reload();
} }
update_buttons_labels(table);
}); });
$('table.table_recap tbody').on('click', 'tr', function () { $('table.table_recap tbody').on('click', 'tr', function () {
if ($(this).hasClass('selected')) { if ($(this).hasClass('selected')) {