Améliore formsemestre_list_saisies_notes

This commit is contained in:
Emmanuel Viennet 2024-11-08 00:15:39 +01:00
parent 07423e08b6
commit 6cd28853bc
8 changed files with 153 additions and 40 deletions

View File

@ -141,7 +141,7 @@ class Assiduite(ScoDocModel):
}"""
def __repr__(self) -> str:
return f"<Assiduite {self.id}: {self.__str__()}>"
return f"<Assiduite {self.id}: {self.etudiant.nom}: {self.__str__()}>"
@classmethod
def create_assiduite(

View File

@ -127,6 +127,12 @@ class Identite(models.ScoDocModel):
cascade="all, delete-orphan",
lazy="dynamic",
)
notes_log = db.relationship(
"NotesNotesLog",
backref="etudiant",
cascade="all, delete-orphan",
lazy="dynamic",
)
# Relations avec les assiduites et les justificatifs
assiduites = db.relationship(
"Assiduite", back_populates="etudiant", lazy="dynamic", cascade="all, delete"

View File

@ -64,6 +64,13 @@ class Evaluation(models.ScoDocModel):
cascade="all, delete-orphan",
lazy="dynamic",
)
notes_log = db.relationship(
"NotesNotesLog",
backref="evaluation",
cascade="all, delete-orphan",
lazy="dynamic",
primaryjoin="Evaluation.id == foreign(NotesNotesLog.evaluation_id)",
)
ues = db.relationship("UniteEns", secondary="evaluation_ue_poids", viewonly=True)
_sco_dept_relations = ("ModuleImpl", "FormSemestre") # accès au dept_id

View File

@ -499,11 +499,7 @@ class GenTable:
H.append(caption)
if self.base_url:
H.append('<span class="gt_export_icons">')
if self.xls_link:
H.append(
f""" <a href="{add_query_param(self.base_url, "fmt", "xls")
}">{scu.ICON_XLS}</a>"""
)
H.append(self.xls_export_button())
if self.xls_link and self.pdf_link:
H.append("&nbsp;")
if self.pdf_link:
@ -517,6 +513,15 @@ class GenTable:
H.append(self.html_next_section)
return "\n".join(H)
def xls_export_button(self) -> str:
"markup pour export excel"
return (
f""" <a href="{add_query_param(self.base_url, "fmt", "xls")
}">{scu.ICON_XLS}</a>"""
if self.xls_link
else ""
)
def excel(self, wb=None):
"""Simple Excel representation of the table"""
if wb is None:

View File

@ -46,9 +46,11 @@ Opérations:
"""
import datetime
from flask import g, request, url_for
from flask import g, render_template, request, url_for
from app.models import Evaluation, FormSemestre
from app import db
from app.auth.models import User
from app.models import Evaluation, FormSemestre, ModuleImpl, NotesNotes, NotesNotesLog
from app.scodoc.intervals import intervalmap
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
@ -178,36 +180,67 @@ def evaluation_list_operations(evaluation_id: int):
return tab.make_page()
def formsemestre_list_saisies_notes(formsemestre_id, fmt="html"):
def formsemestre_list_saisies_notes(formsemestre_id, only_modifs=False, fmt="html"):
"""Table listant toutes les opérations de saisies de notes, dans toutes
les évaluations du semestre.
"""
formsemestre: FormSemestre = FormSemestre.get_or_404(formsemestre_id)
rows = ndb.SimpleDictFetch(
"""SELECT i.nom, i.prenom, code_nip, n.*, mod.titre, e.description, e.date_debut,
u.user_name, e.id as evaluation_id
FROM notes_notes n, notes_evaluation e, notes_moduleimpl mi,
notes_modules mod, identite i, "user" u
WHERE mi.id = e.moduleimpl_id
and mi.module_id = mod.id
and e.id = n.evaluation_id
and i.id = n.etudid
and u.id = n.uid
and mi.formsemestre_id = %(formsemestre_id)s
ORDER BY date desc
""",
{"formsemestre_id": formsemestre_id},
formsemestre: FormSemestre = FormSemestre.get_formsemestre(formsemestre_id)
only_modifs = scu.to_bool(only_modifs)
model = NotesNotesLog if only_modifs else NotesNotes
notes_query = (
db.session.query(model)
.join(Evaluation, Evaluation.id == model.evaluation_id)
.join(ModuleImpl)
.filter_by(formsemestre_id=formsemestre.id)
.order_by(model.date.desc())
)
# Formate les notes
keep_numeric = fmt in scu.FORMATS_NUMERIQUES
for row in rows:
row["value"] = scu.fmt_note(row["value"], keep_numeric=keep_numeric)
row["date_evaluation"] = (
row["date_debut"].strftime("%d/%m/%Y %H:%M") if row["date_debut"] else ""
)
row["_date_evaluation_order"] = (
row["date_debut"].isoformat() if row["date_debut"] else ""
rows = []
for note in notes_query:
ens = User.get_user(note.uid)
evaluation = note.evaluation
rows.append(
{
"date": note.date.strftime(scu.DATEATIME_FMT),
"_date_order": note.date.isoformat(),
"code_nip": note.etudiant.code_nip,
"nom": note.etudiant.nom_disp(),
"prenom": note.etudiant.prenom_str,
"date_evaluation": (
evaluation.date_debut.strftime(scu.DATEATIME_FMT)
if evaluation and note.evaluation.date_debut
else ""
),
"_date_evaluation_order": (
note.evaluation.date_debut.isoformat()
if evaluation and note.evaluation.date_debut
else ""
),
"value": scu.fmt_note(note.value, keep_numeric=keep_numeric),
"module": (
(
note.evaluation.moduleimpl.module.code
or note.evaluation.moduleimpl.module.titre
)
if evaluation
else ""
),
"evaluation": note.evaluation.description if evaluation else "",
"_evaluation_target": (
url_for(
"notes.evaluation_listenotes",
scodoc_dept=g.scodoc_dept,
evaluation_id=note.evaluation_id,
)
if evaluation
else ""
),
"user_name": ens.user_name if ens else "",
}
)
columns_ids = (
"date",
"code_nip",
@ -215,9 +248,8 @@ def formsemestre_list_saisies_notes(formsemestre_id, fmt="html"):
"prenom",
"value",
"user_name",
"titre",
"evaluation_id",
"description",
"module",
"evaluation",
"date_evaluation",
"comment",
)
@ -230,11 +262,11 @@ def formsemestre_list_saisies_notes(formsemestre_id, fmt="html"):
"comment": "Remarque",
"user_name": "Enseignant",
"evaluation_id": "evaluation_id",
"titre": "Module",
"description": "Evaluation",
"module": "Module",
"evaluation": "Evaluation",
"date_evaluation": "Date éval.",
}
tab = GenTable(
table = GenTable(
titles=titles,
columns_ids=columns_ids,
rows=rows,
@ -244,11 +276,25 @@ def formsemestre_list_saisies_notes(formsemestre_id, fmt="html"):
html_sortable=True,
caption=f"Saisies de notes dans {formsemestre.titre_annee()}",
preferences=sco_preferences.SemPreferences(formsemestre_id),
base_url="%s?formsemestre_id=%s" % (request.base_url, formsemestre_id),
base_url=f"""{request.base_url}?formsemestre_id={
formsemestre_id}&only_modifs={int(only_modifs)}""",
origin=f"Généré par {sco_version.SCONAME} le " + scu.timedate_human_repr() + "",
table_id="formsemestre_list_saisies_notes",
filename=(
f"modifs_notes_S{formsemestre.semestre_id}"
if only_modifs
else f"saisies_notes_S{formsemestre.semestre_id}"
),
)
return tab.make_page(fmt=fmt)
if fmt == "html":
return render_template(
"formsemestre/list_saisies_notes.j2",
table=table,
title="Opérations de saisies de notes",
only_modifs=only_modifs,
formsemestre_id=formsemestre.id,
)
return table.make_page(fmt=fmt, page_title="Opérations de saisies de notes")
def get_note_history(evaluation_id, etudid, fmt=""):

View File

@ -0,0 +1,48 @@
{% extends "sco_page.j2" %}
{% block styles %}
{{super()}}
<style>
.export_xls_but {
margin-left: 32px;
}
</style>
{% endblock %}
{% block app_content %}
<h2 class="formsemestre">{{title_h2}}</h2>
<div>{{table.get_nb_rows()}}
{% if only_modifs %}modifications{% else %}saisies{% endif %}
de notes dans ce semestre.
</div>
<form id="filter-form">
<label>
<input type="checkbox" id="only-modifs-checkbox" name="only_modifs" value="1"
{% if only_modifs %}checked{% endif %}>
Lister uniquement les modifications
</label>
<span class="export_xls_but">{{table.xls_export_button()|safe}} excel</span>
</form>
{{table.html()|safe}}
{% endblock %}
{% block scripts %}
{{super()}}
<script>
document.getElementById('only-modifs-checkbox').addEventListener('change', function() {
var form = document.getElementById('filter-form');
var onlyModifs = this.checked ? '1' : '0';
var url = new URL(window.location.href);
url.searchParams.set('formsemestre_id', {{formsemestre_id}});
url.searchParams.set('only_modifs', onlyModifs);
window.location.href = url.toString();
});
</script>
{% endblock %}

View File

@ -3,7 +3,7 @@
"Infos sur version ScoDoc"
SCOVERSION = "9.7.39"
SCOVERSION = "9.7.40"
SCONAME = "ScoDoc"

View File

@ -94,6 +94,7 @@ def test_permissions(api_headers):
"/ScoDoc/api/justificatif/1/list", # demande AbsJustifView
"/ScoDoc/api/justificatif/1/justifies", # demande ScoJustifChange
"/ScoDoc/api/justificatif/1/export", # demande AbsChange
"/ScoDoc/api/operations/user/", # demande superamin ou user lui même
]
):
# On passe ces routes spéciales