Compare commits

...

3 Commits

28 changed files with 1205 additions and 1126 deletions

View File

@ -9,12 +9,14 @@
import collections import collections
import datetime import datetime
import pandas as pd
import numpy as np import numpy as np
from flask import g, has_request_context, url_for from flask import g, has_request_context, url_for
from app import db from app import db
from app.comp.moy_mod import ModuleImplResults
from app.comp.res_but import ResultatsSemestreBUT from app.comp.res_but import ResultatsSemestreBUT
from app.models import Evaluation, FormSemestre, Identite from app.models import Evaluation, FormSemestre, Identite, ModuleImpl
from app.models.groups import GroupDescr from app.models.groups import GroupDescr
from app.models.ues import UniteEns from app.models.ues import UniteEns
from app.scodoc import sco_bulletins, sco_utils as scu from app.scodoc import sco_bulletins, sco_utils as scu
@ -249,59 +251,88 @@ class BulletinBUT:
# "moy": fmt_note(moyennes_etuds.mean()), # "moy": fmt_note(moyennes_etuds.mean()),
}, },
"evaluations": ( "evaluations": (
[ self.etud_list_modimpl_evaluations(
self.etud_eval_results(etud, e) etud, modimpl, modimpl_results, version
for e in modimpl.evaluations )
if (e.visibulletin or version == "long")
and (e.id in modimpl_results.evaluations_etat)
and (
modimpl_results.evaluations_etat[e.id].is_complete
or self.prefs["bul_show_all_evals"]
)
]
if version != "short" if version != "short"
else [] else []
), ),
} }
return d return d
def etud_eval_results(self, etud, e: Evaluation) -> dict: def etud_list_modimpl_evaluations(
self,
etud: Identite,
modimpl: ModuleImpl,
modimpl_results: ModuleImplResults,
version: str,
) -> list[dict]:
"""Liste des résultats aux évaluations de ce modimpl à montrer pour cet étudiant"""
evaluation: Evaluation
eval_results = []
for evaluation in modimpl.evaluations:
if (
(evaluation.visibulletin or version == "long")
and (evaluation.id in modimpl_results.evaluations_etat)
and (
modimpl_results.evaluations_etat[evaluation.id].is_complete
or self.prefs["bul_show_all_evals"]
)
):
eval_notes = self.res.modimpls_results[modimpl.id].evals_notes[
evaluation.id
]
if (evaluation.evaluation_type == Evaluation.EVALUATION_NORMALE) or (
not np.isnan(eval_notes[etud.id])
):
eval_results.append(
self.etud_eval_results(etud, evaluation, eval_notes)
)
return eval_results
def etud_eval_results(
self, etud: Identite, evaluation: Evaluation, eval_notes: pd.DataFrame
) -> dict:
"dict resultats d'un étudiant à une évaluation" "dict resultats d'un étudiant à une évaluation"
# eval_notes est une pd.Series avec toutes les notes des étudiants inscrits # 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]
notes_ok = eval_notes.where(eval_notes > scu.NOTES_ABSENCE).dropna() notes_ok = eval_notes.where(eval_notes > scu.NOTES_ABSENCE).dropna()
modimpls_evals_poids = self.res.modimpls_evals_poids[e.moduleimpl_id] modimpls_evals_poids = self.res.modimpls_evals_poids[evaluation.moduleimpl_id]
try: try:
etud_ues_ids = self.res.etud_ues_ids(etud.id) etud_ues_ids = self.res.etud_ues_ids(etud.id)
poids = { poids = {
ue.acronyme: modimpls_evals_poids[ue.id][e.id] ue.acronyme: modimpls_evals_poids[ue.id][evaluation.id]
for ue in self.res.ues for ue in self.res.ues
if (ue.type != UE_SPORT) and (ue.id in etud_ues_ids) if (ue.type != UE_SPORT) and (ue.id in etud_ues_ids)
} }
except KeyError: except KeyError:
poids = collections.defaultdict(lambda: 0.0) poids = collections.defaultdict(lambda: 0.0)
d = { d = {
"id": e.id, "id": evaluation.id,
"coef": ( "coef": (
fmt_note(e.coefficient) fmt_note(evaluation.coefficient)
if e.evaluation_type == Evaluation.EVALUATION_NORMALE if evaluation.evaluation_type == Evaluation.EVALUATION_NORMALE
else None else None
), ),
"date_debut": e.date_debut.isoformat() if e.date_debut else None, "date_debut": (
"date_fin": e.date_fin.isoformat() if e.date_fin else None, evaluation.date_debut.isoformat() if evaluation.date_debut else None
"description": e.description, ),
"evaluation_type": e.evaluation_type, "date_fin": (
evaluation.date_fin.isoformat() if evaluation.date_fin else None
),
"description": evaluation.description,
"evaluation_type": evaluation.evaluation_type,
"note": ( "note": (
{ {
"value": fmt_note( "value": fmt_note(
eval_notes[etud.id], eval_notes[etud.id],
note_max=e.note_max, note_max=evaluation.note_max,
), ),
"min": fmt_note(notes_ok.min(), note_max=e.note_max), "min": fmt_note(notes_ok.min(), note_max=evaluation.note_max),
"max": fmt_note(notes_ok.max(), note_max=e.note_max), "max": fmt_note(notes_ok.max(), note_max=evaluation.note_max),
"moy": fmt_note(notes_ok.mean(), note_max=e.note_max), "moy": fmt_note(notes_ok.mean(), note_max=evaluation.note_max),
} }
if not e.is_blocked() if not evaluation.is_blocked()
else {} else {}
), ),
"poids": poids, "poids": poids,
@ -309,17 +340,25 @@ class BulletinBUT:
url_for( url_for(
"notes.evaluation_listenotes", "notes.evaluation_listenotes",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
evaluation_id=e.id, evaluation_id=evaluation.id,
) )
if has_request_context() if has_request_context()
else "na" else "na"
), ),
# deprecated (supprimer avant #sco9.7) # deprecated (supprimer avant #sco9.7)
"date": e.date_debut.isoformat() if e.date_debut else None, "date": (
"heure_debut": ( evaluation.date_debut.isoformat() if evaluation.date_debut else None
e.date_debut.time().isoformat("minutes") if e.date_debut else None ),
"heure_debut": (
evaluation.date_debut.time().isoformat("minutes")
if evaluation.date_debut
else None
),
"heure_fin": (
evaluation.date_fin.time().isoformat("minutes")
if evaluation.date_fin
else None
), ),
"heure_fin": e.date_fin.time().isoformat("minutes") if e.date_fin else None,
} }
return d return d

View File

@ -48,6 +48,7 @@ from typing import Any
from urllib.parse import urlparse, urlencode, parse_qs, urlunparse from urllib.parse import urlparse, urlencode, parse_qs, urlunparse
from openpyxl.utils import get_column_letter from openpyxl.utils import get_column_letter
import reportlab
from reportlab.platypus import Paragraph, Spacer from reportlab.platypus import Paragraph, Spacer
from reportlab.platypus import Table, KeepInFrame from reportlab.platypus import Table, KeepInFrame
from reportlab.lib.colors import Color from reportlab.lib.colors import Color
@ -812,7 +813,10 @@ if __name__ == "__main__":
document, document,
) )
) )
document.build(objects) try:
document.build(objects)
except (ValueError, KeyError, reportlab.platypus.doctemplate.LayoutError) as exc:
raise ScoPDFFormatError(str(exc)) from exc
data = doc.getvalue() data = doc.getvalue()
with open("/tmp/gen_table.pdf", "wb") as f: with open("/tmp/gen_table.pdf", "wb") as f:
f.write(data) f.write(data)

View File

@ -446,7 +446,8 @@ def _ue_mod_bulletin(
): ):
"""Infos sur les modules (et évaluations) dans une UE """Infos sur les modules (et évaluations) dans une UE
(ajoute les informations aux modimpls) (ajoute les informations aux modimpls)
Result: liste de modules de l'UE avec les infos dans chacun (seulement ceux où l'étudiant est inscrit). Result: liste de modules de l'UE avec les infos dans chacun (seulement
ceux l'étudiant est inscrit).
""" """
bul_show_mod_rangs = sco_preferences.get_preference( bul_show_mod_rangs = sco_preferences.get_preference(
"bul_show_mod_rangs", formsemestre_id "bul_show_mod_rangs", formsemestre_id

View File

@ -61,7 +61,7 @@ from flask_login import current_user
from app.models import FormSemestre, Identite, ScoDocSiteConfig from app.models import FormSemestre, Identite, ScoDocSiteConfig
from app.scodoc import sco_utils as scu from app.scodoc import sco_utils as scu
from app.scodoc.sco_exceptions import NoteProcessError from app.scodoc.sco_exceptions import NoteProcessError, ScoPDFFormatError
from app import log from app import log
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
from app.scodoc import sco_pdf from app.scodoc import sco_pdf
@ -228,7 +228,15 @@ class BulletinGenerator:
preferences=sco_preferences.SemPreferences(formsemestre_id), preferences=sco_preferences.SemPreferences(formsemestre_id),
) )
) )
document.build(story) try:
document.build(story)
except (
ValueError,
KeyError,
reportlab.platypus.doctemplate.LayoutError,
) as exc:
raise ScoPDFFormatError(str(exc)) from exc
data = report.getvalue() data = report.getvalue()
return data return data

View File

@ -103,7 +103,7 @@ class ScoPDFFormatError(ScoValueError):
super().__init__( super().__init__(
f"""Erreur dans un format pdf: f"""Erreur dans un format pdf:
<p>{msg}</p> <p>{msg}</p>
<p>Vérifiez les paramètres (polices de caractères, balisage) <p>Vérifiez les paramètres (polices de caractères, balisage, réglages bulletins...)
dans les paramètres ou préférences. dans les paramètres ou préférences.
</p> </p>
""", """,

View File

@ -458,7 +458,12 @@ def pdf_basic_page(
if title: if title:
head = Paragraph(SU(title), StyleSheet["Heading3"]) head = Paragraph(SU(title), StyleSheet["Heading3"])
objects = [head] + objects objects = [head] + objects
document.build(objects)
try:
document.build(objects)
except (ValueError, KeyError, reportlab.platypus.doctemplate.LayoutError) as exc:
raise ScoPDFFormatError(str(exc)) from exc
data = report.getvalue() data = report.getvalue()
return data return data

View File

@ -50,7 +50,7 @@ from app.scodoc import sco_bulletins_pdf
from app.scodoc import sco_pv_dict from app.scodoc import sco_pv_dict
from app.scodoc import sco_pdf from app.scodoc import sco_pdf
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoPDFFormatError, ScoValueError
from app.scodoc.sco_cursus_dut import SituationEtudCursus from app.scodoc.sco_cursus_dut import SituationEtudCursus
from app.scodoc.sco_pv_templates import CourrierIndividuelTemplate, jury_titres from app.scodoc.sco_pv_templates import CourrierIndividuelTemplate, jury_titres
import sco_version import sco_version
@ -132,7 +132,11 @@ def pdf_lettres_individuelles(
) )
) )
document.build(objects) try:
document.build(objects)
except (ValueError, KeyError, reportlab.platypus.doctemplate.LayoutError) as exc:
raise ScoPDFFormatError(str(exc)) from exc
data = report.getvalue() data = report.getvalue()
return data return data
@ -241,13 +245,14 @@ def pdf_lettre_individuelle(sem, decision, etud: Identite, params, signature=Non
titre_jury_court = "s" titre_jury_court = "s"
else: else:
titre_jury_court = "" titre_jury_court = ""
params[ params["autorisations_txt"] = (
"autorisations_txt" """Vous êtes autorisé%s à continuer dans le%s semestre%s : <b>%s</b>"""
] = """Vous êtes autorisé%s à continuer dans le%s semestre%s : <b>%s</b>""" % ( % (
etud.e, etud.e,
titre_jury_court, titre_jury_court,
titre_jury_court, titre_jury_court,
decision["autorisations_descr"], decision["autorisations_descr"],
)
) )
else: else:
params["autorisations_txt"] = "" params["autorisations_txt"] = ""

View File

@ -126,7 +126,11 @@ def pvjury_pdf(
) )
) )
document.build(objects) try:
document.build(objects)
except (ValueError, KeyError, reportlab.platypus.doctemplate.LayoutError) as exc:
raise ScoPDFFormatError(str(exc)) from exc
data = report.getvalue() data = report.getvalue()
return data return data

View File

@ -47,12 +47,11 @@ from app import db, log
from app.models import Identite from app.models import Identite
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoPDFFormatError, ScoValueError
from app.scodoc.sco_pdf import SU from app.scodoc.sco_pdf import SU
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
from app.scodoc import htmlutils from app.scodoc import htmlutils
from app.scodoc import sco_import_etuds from app.scodoc import sco_import_etuds
from app.scodoc import sco_etud
from app.scodoc import sco_excel from app.scodoc import sco_excel
from app.scodoc import sco_groups_view from app.scodoc import sco_groups_view
from app.scodoc import sco_pdf from app.scodoc import sco_pdf
@ -388,7 +387,10 @@ def _trombino_pdf(groups_infos):
preferences=sco_preferences.SemPreferences(sem["formsemestre_id"]), preferences=sco_preferences.SemPreferences(sem["formsemestre_id"]),
) )
) )
document.build(objects) try:
document.build(objects)
except (ValueError, KeyError, reportlab.platypus.doctemplate.LayoutError) as exc:
raise ScoPDFFormatError(str(exc)) from exc
report.seek(0) report.seek(0)
return send_file( return send_file(
report, report,
@ -465,7 +467,10 @@ def _listeappel_photos_pdf(groups_infos):
preferences=sco_preferences.SemPreferences(sem["formsemestre_id"]), preferences=sco_preferences.SemPreferences(sem["formsemestre_id"]),
) )
) )
document.build(objects) try:
document.build(objects)
except (ValueError, KeyError, reportlab.platypus.doctemplate.LayoutError) as exc:
raise ScoPDFFormatError(str(exc)) from exc
data = report.getvalue() data = report.getvalue()
return scu.sendPDFFile(data, filename) return scu.sendPDFFile(data, filename)

View File

@ -31,7 +31,7 @@
""" """
import io import io
import reportlab
from reportlab.lib import colors from reportlab.lib import colors
from reportlab.lib.colors import black from reportlab.lib.colors import black
from reportlab.lib.pagesizes import A4, A3 from reportlab.lib.pagesizes import A4, A3
@ -277,10 +277,12 @@ def pdf_trombino_tours(
preferences=sco_preferences.SemPreferences(), preferences=sco_preferences.SemPreferences(),
) )
) )
try: try:
document.build(objects) document.build(objects)
except (ValueError, KeyError) as exc: except (ValueError, KeyError, reportlab.platypus.doctemplate.LayoutError) as exc:
raise ScoPDFFormatError(str(exc)) from exc raise ScoPDFFormatError(str(exc)) from exc
data = report.getvalue() data = report.getvalue()
return scu.sendPDFFile(data, filename) return scu.sendPDFFile(data, filename)
@ -470,7 +472,10 @@ def pdf_feuille_releve_absences(
preferences=sco_preferences.SemPreferences(), preferences=sco_preferences.SemPreferences(),
) )
) )
document.build(objects) try:
document.build(objects)
except (ValueError, KeyError, reportlab.platypus.doctemplate.LayoutError) as exc:
raise ScoPDFFormatError(str(exc)) from exc
data = report.getvalue() data = report.getvalue()
return scu.sendPDFFile(data, filename) return scu.sendPDFFile(data, filename)

View File

@ -1,6 +1,6 @@
function _partition_set_attr(partition_id, attr_name, attr_value) { function _partition_set_attr(partition_id, attr_name, attr_value) {
$.post( $.post(
SCO_URL + "/partition_set_attr", SCO_URL + "partition_set_attr",
{ {
partition_id: partition_id, partition_id: partition_id,
attr: attr_name, attr: attr_name,

View File

@ -33,7 +33,7 @@ function update_ue_list() {
let ue_code = $("#tf_ue_code")[0].value; let ue_code = $("#tf_ue_code")[0].value;
let query = let query =
SCO_URL + SCO_URL +
"/Notes/ue_sharing_code?ue_code=" + "Notes/ue_sharing_code?ue_code=" +
ue_code + ue_code +
"&hide_ue_id=" + "&hide_ue_id=" +
ue_id + ue_id +

View File

@ -16,7 +16,7 @@ function display_itemsuivis(active) {
.off("click") .off("click")
.click(function (e) { .click(function (e) {
e.preventDefault(); e.preventDefault();
$.post(SCO_URL + "/itemsuivi_create", { $.post(SCO_URL + "itemsuivi_create", {
etudid: etudid, etudid: etudid,
fmt: "json", fmt: "json",
}).done(item_insert_new); }).done(item_insert_new);
@ -26,7 +26,7 @@ function display_itemsuivis(active) {
} }
// add existing items // add existing items
$.get( $.get(
SCO_URL + "/itemsuivi_list_etud", SCO_URL + "itemsuivi_list_etud",
{ etudid: etudid, fmt: "json" }, { etudid: etudid, fmt: "json" },
function (L) { function (L) {
for (var i in L) { for (var i in L) {
@ -95,7 +95,7 @@ function item_nodes(itemsuivi_id, item_date, situation, tags, readonly) {
dp.blur(function (e) { dp.blur(function (e) {
var date = this.value; var date = this.value;
// console.log('selected text: ' + date); // console.log('selected text: ' + date);
$.post(SCO_URL + "/itemsuivi_set_date", { $.post(SCO_URL + "itemsuivi_set_date", {
item_date: date, item_date: date,
itemsuivi_id: itemsuivi_id, itemsuivi_id: itemsuivi_id,
}); });
@ -103,7 +103,7 @@ function item_nodes(itemsuivi_id, item_date, situation, tags, readonly) {
dp.datepicker({ dp.datepicker({
onSelect: function (date, instance) { onSelect: function (date, instance) {
// console.log('selected: ' + date + 'for itemsuivi_id ' + itemsuivi_id); // console.log('selected: ' + date + 'for itemsuivi_id ' + itemsuivi_id);
$.post(SCO_URL + "/itemsuivi_set_date", { $.post(SCO_URL + "itemsuivi_set_date", {
item_date: date, item_date: date,
itemsuivi_id: itemsuivi_id, itemsuivi_id: itemsuivi_id,
}); });
@ -161,7 +161,7 @@ function Date2DMY(date) {
} }
function itemsuivi_suppress(itemsuivi_id) { function itemsuivi_suppress(itemsuivi_id) {
$.post(SCO_URL + "/itemsuivi_suppress", { itemsuivi_id: itemsuivi_id }); $.post(SCO_URL + "itemsuivi_suppress", { itemsuivi_id: itemsuivi_id });
// Clear items and rebuild: // Clear items and rebuild:
$("ul.listdebouches li.itemsuivi").remove(); $("ul.listdebouches li.itemsuivi").remove();
display_itemsuivis(0); display_itemsuivis(0);

View File

@ -37,7 +37,7 @@ $().ready(function () {
ajax: { ajax: {
url: url:
SCO_URL + SCO_URL +
"/etud_info_html?etudid=" + "etud_info_html?etudid=" +
get_etudid_from_elem(elems[i]) + get_etudid_from_elem(elems[i]) +
qs, qs,
type: "GET", type: "GET",

View File

@ -19,7 +19,7 @@ function loadGroupes() {
$("#gmsg")[0].style.display = "block"; $("#gmsg")[0].style.display = "block";
var partition_id = document.formGroup.partition_id.value; var partition_id = document.formGroup.partition_id.value;
$.get(SCO_URL + "/XMLgetGroupsInPartition", { $.get(SCO_URL + "XMLgetGroupsInPartition", {
partition_id: partition_id, partition_id: partition_id,
}).done(function (data) { }).done(function (data) {
var nodes = data.getElementsByTagName("group"); var nodes = data.getElementsByTagName("group");
@ -384,7 +384,7 @@ function handleError(msg) {
} }
function submitGroups() { function submitGroups() {
var url = SCO_URL + "/setGroups"; var url = SCO_URL + "setGroups";
// build post request body: groupname \n etudid; ... // build post request body: groupname \n etudid; ...
var groupsLists = ""; var groupsLists = "";
var groupsToCreate = ""; var groupsToCreate = "";
@ -443,7 +443,7 @@ function GotoAnother() {
} else } else
document.location = document.location =
SCO_URL + SCO_URL +
"/affect_groups?partition_id=" + "affect_groups?partition_id=" +
document.formGroup.other_partition_id.value; document.formGroup.other_partition_id.value;
} }

View File

@ -5,7 +5,7 @@ $().ready(function () {
for (var i = 0; i < spans.length; i++) { for (var i = 0; i < spans.length; i++) {
var sp = spans[i]; var sp = spans[i];
var etudid = sp.id; var etudid = sp.id;
$(sp).load(SCO_URL + "/etud_photo_html?etudid=" + etudid); $(sp).load(SCO_URL + "etud_photo_html?etudid=" + etudid);
} }
}); });
@ -194,7 +194,7 @@ $().ready(function () {
ajax: { ajax: {
url: url:
SCO_URL + SCO_URL +
"/etud_info_html?with_photo=0&etudid=" + "etud_info_html?with_photo=0&etudid=" +
get_etudid_from_elem(elems[i]), get_etudid_from_elem(elems[i]),
}, },
text: "Loading...", text: "Loading...",

View File

@ -34,7 +34,7 @@ function get_notes_and_draw(formsemestre_id, etudid) {
*/ */
var query = var query =
SCO_URL + SCO_URL +
"/Notes/formsemestre_bulletinetud?formsemestre_id=" + "Notes/formsemestre_bulletinetud?formsemestre_id=" +
formsemestre_id + formsemestre_id +
"&etudid=" + "&etudid=" +
etudid + etudid +

View File

@ -42,7 +42,7 @@ async function save_note(elem, v, etudid) {
$("#sco_msg").html("en cours...").show(); $("#sco_msg").html("en cours...").show();
try { try {
const response = await fetch( const response = await fetch(
SCO_URL + "/../api/evaluation/" + evaluation_id + "/notes/set", SCO_URL + "../api/evaluation/" + evaluation_id + "/notes/set",
{ {
method: "POST", method: "POST",
headers: { headers: {

View File

@ -6,7 +6,7 @@ $(function () {
delay: 300, // wait 300ms before suggestions delay: 300, // wait 300ms before suggestions
minLength: 2, // min nb of chars before suggest minLength: 2, // min nb of chars before suggest
position: { collision: "flip" }, // automatic menu position up/down position: { collision: "flip" }, // automatic menu position up/down
source: SCO_URL + "/search_etud_by_name", source: SCO_URL + "search_etud_by_name",
select: function (event, ui) { select: function (event, ui) {
$(".in-expnom").val(ui.item.value); $(".in-expnom").val(ui.item.value);
$("#form-chercheetud").submit(); $("#form-chercheetud").submit();

View File

@ -5,6 +5,6 @@ $().ready(function () {
for (var i = 0; i < spans.size(); i++) { for (var i = 0; i < spans.size(); i++) {
var sp = spans[i]; var sp = spans[i];
var etudid = sp.id; var etudid = sp.id;
$(sp).load(SCO_URL + "/etud_photo_html?etudid=" + etudid); $(sp).load(SCO_URL + "etud_photo_html?etudid=" + etudid);
} }
}); });

View File

@ -22,7 +22,7 @@ document.addEventListener("DOMContentLoaded", () => {
async function delete_validation(etudid, validation_type, validation_id) { async function delete_validation(etudid, validation_type, validation_id) {
const response = await fetch( const response = await fetch(
`${SCO_URL}/../api/etudiant/${etudid}/jury/${validation_type}/${validation_id}/delete`, `${SCO_URL}../api/etudiant/${etudid}/jury/${validation_type}/${validation_id}/delete`,
{ {
method: "POST", method: "POST",
} }
@ -38,7 +38,7 @@ async function delete_validation(etudid, validation_type, validation_id) {
function update_ue_list() { function update_ue_list() {
var ue_id = $("#tf_ue_id")[0].value; var ue_id = $("#tf_ue_id")[0].value;
if (ue_id) { if (ue_id) {
var query = SCO_URL + "/Notes/ue_sharing_code?ue_id=" + ue_id; var query = SCO_URL + "Notes/ue_sharing_code?ue_id=" + ue_id;
$.get(query, "", function (data) { $.get(query, "", function (data) {
$("#ue_list_code").html(data); $("#ue_list_code").html(data);
}); });

View File

@ -149,7 +149,7 @@ Calendrier de l'assiduité
list-style-type: none; list-style-type: none;
} }
.pageContent { .pageContent {
margin-top: 1vh; margin-top: 1vh;
@ -335,7 +335,7 @@ Calendrier de l'assiduité
document.querySelectorAll('[assi_id]').forEach((el, i) => { document.querySelectorAll('[assi_id]').forEach((el, i) => {
el.addEventListener('click', () => { el.addEventListener('click', () => {
const assi_id = el.getAttribute('assi_id'); const assi_id = el.getAttribute('assi_id');
window.open(`${SCO_URL}/Assiduites/tableau_assiduite_actions?type=assiduite&action=details&obj_id=${assi_id}`); window.open(`${SCO_URL}Assiduites/tableau_assiduite_actions?type=assiduite&action=details&obj_id=${assi_id}`);
}) })
}); });

View File

@ -102,6 +102,6 @@
<script src="{{scu.STATIC_DIR}}/js/scodoc.js"></script> <script src="{{scu.STATIC_DIR}}/js/scodoc.js"></script>
<script> <script>
const SCO_URL = "{% if g.scodoc_dept %}{{ const SCO_URL = "{% if g.scodoc_dept %}{{
url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)[:-11] }}{% endif %}"; url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)}}{% endif %}";
</script> </script>
{% endblock %} {% endblock %}

View File

@ -152,7 +152,7 @@ document.addEventListener('DOMContentLoaded', function() {
calendar = new Calendar(container, options); calendar = new Calendar(container, options);
fetch(`${SCO_URL}/../api/formsemestre/{{formsemestre.id}}/edt?{{groups_query_args|safe}}&show_modules_titles={{show_modules_titles}}`) fetch(`${SCO_URL}../api/formsemestre/{{formsemestre.id}}/edt?{{groups_query_args|safe}}&show_modules_titles={{show_modules_titles}}`)
.then(r=>{return r.json()}) .then(r=>{return r.json()})
.then(events=>{ .then(events=>{
if (typeof events == 'string') { if (typeof events == 'string') {

View File

@ -17,8 +17,8 @@ et permet de les effacer une par une.
<p class="help"> <p class="help">
<b>Attention</b>, il vous appartient de vérifier la cohérence du résultat ! <b>Attention</b>, il vous appartient de vérifier la cohérence du résultat !
En principe, <b>l'usage de cette page devrait rester exceptionnel</b>. En principe, <b>l'usage de cette page devrait rester exceptionnel</b>.
Aucune annulation n'est ici possible (vous devrez re-saisir les décisions via les Aucune annulation n'est ici possible (vous devrez re-saisir les décisions via les
pages de saisie de jury habituelles). pages de saisie de jury habituelles).
</p> </p>
{% if sem_vals.first() %} {% if sem_vals.first() %}
<div class="jury_decisions_list jury_decisions_sems"> <div class="jury_decisions_list jury_decisions_sems">
@ -27,7 +27,7 @@ pages de saisie de jury habituelles).
{% for v in sem_vals %} {% for v in sem_vals %}
<li>{{v.html()|safe}} <li>{{v.html()|safe}}
<form> <form>
<button <button
data-v_id="{{v.id}}" data-type="validation_formsemestre" data-etudid="{{etud.id}}" data-v_id="{{v.id}}" data-type="validation_formsemestre" data-etudid="{{etud.id}}"
>effacer</button></form> >effacer</button></form>
</li> </li>
@ -101,8 +101,8 @@ pages de saisie de jury habituelles).
{% endif %} {% endif %}
{% if not( {% if not(
sem_vals.first() or ue_vals.first() or rcue_vals.first() sem_vals.first() or ue_vals.first() or rcue_vals.first()
or annee_but_vals.first() or autorisations.first()) or annee_but_vals.first() or autorisations.first())
%} %}
<div> <div>
<p class="fontred">aucune décision enregistrée</p> <p class="fontred">aucune décision enregistrée</p>
@ -123,7 +123,7 @@ pages de saisie de jury habituelles).
<script> <script>
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const buttons = document.querySelectorAll('.jury_decisions_list button'); const buttons = document.querySelectorAll('.jury_decisions_list button');
buttons.forEach(button => { buttons.forEach(button => {
button.addEventListener('click', (event) => { button.addEventListener('click', (event) => {
// Handle button click event here // Handle button click event here
@ -132,10 +132,10 @@ document.addEventListener('DOMContentLoaded', () => {
const v_id = event.target.dataset.v_id; const v_id = event.target.dataset.v_id;
const validation_type = event.target.dataset.type; const validation_type = event.target.dataset.type;
if (confirm("Supprimer cette validation ?")) { if (confirm("Supprimer cette validation ?")) {
fetch(`${SCO_URL}/../api/etudiant/${etudid}/jury/${validation_type}/${v_id}/delete`, fetch(`${SCO_URL}../api/etudiant/${etudid}/jury/${validation_type}/${v_id}/delete`,
{ {
method: "POST", method: "POST",
}).then(response => { }).then(response => {
// Handle the response // Handle the response
if (response.ok) { if (response.ok) {
location.reload(); location.reload();

View File

@ -51,7 +51,7 @@
<script> <script>
window.onload = function () { enableTooltips("gtrcontent") }; window.onload = function () { enableTooltips("gtrcontent") };
const SCO_URL = "{{ url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)[:-11] }}"; const SCO_URL = "{{ url_for('scolar.index_html', scodoc_dept=g.scodoc_dept) }}";
</script> </script>
{% endblock %} {% endblock %}

View File

@ -159,8 +159,9 @@ def anonymize_users(cursor):
# Change les noms/prenoms/mail # Change les noms/prenoms/mail
cursor.execute("""SELECT * FROM "user";""") cursor.execute("""SELECT * FROM "user";""")
users = cursor.fetchall() # fetch tout car modifie cette table ds la boucle users = cursor.fetchall() # fetch tout car modifie cette table ds la boucle
nb_users = len(users)
used_user_names = {u["user_name"] for u in users} used_user_names = {u["user_name"] for u in users}
for user in users: for i, user in enumerate(users):
user_name = user["user_name"] user_name = user["user_name"]
nom, prenom = random.choice(NOMS), random.choice(PRENOMS) nom, prenom = random.choice(NOMS), random.choice(PRENOMS)
new_name = (prenom[0] + nom).lower() new_name = (prenom[0] + nom).lower()
@ -168,7 +169,7 @@ def anonymize_users(cursor):
while new_name in used_user_names: while new_name in used_user_names:
new_name += "x" new_name += "x"
used_user_names.add(new_name) used_user_names.add(new_name)
print(f"{user_name} > {new_name}") print(f"{i}/{nb_users}\t{user_name} > {new_name}")
cursor.execute( cursor.execute(
"""UPDATE "user" """UPDATE "user"
SET nom=%(nom)s, prenom=%(prenom)s, email=%(email)s, user_name=%(new_name)s SET nom=%(nom)s, prenom=%(prenom)s, email=%(email)s, user_name=%(new_name)s
@ -234,6 +235,7 @@ if __name__ == "__main__":
cursor = cnx.cursor(cursor_factory=psycopg2.extras.DictCursor) cursor = cnx.cursor(cursor_factory=psycopg2.extras.DictCursor)
anonymize_db(cursor) anonymize_db(cursor)
rename_students(cursor)
if PROCESS_USERS: if PROCESS_USERS:
anonymize_users(cursor) anonymize_users(cursor)

File diff suppressed because it is too large Load Diff