forked from ScoDoc/ScoDoc
Import notes toutes évaluations d'un module
This commit is contained in:
parent
10623e568b
commit
4de2d63861
@ -830,7 +830,7 @@ def check_etud_duplicate_code(args, code_name, edit=True):
|
|||||||
dest_endpoint = "notes.index_html"
|
dest_endpoint = "notes.index_html"
|
||||||
parameters = {}
|
parameters = {}
|
||||||
|
|
||||||
err_page = f"""<h3><h3>Code étudiant ({code_name}) dupliqué !</h3>
|
err_page = f"""<h3>Code étudiant ({code_name}) dupliqué !</h3>
|
||||||
<p class="help">Le {code_name} {args[code_name]} est déjà utilisé: un seul étudiant peut avoir
|
<p class="help">Le {code_name} {args[code_name]} est déjà utilisé: un seul étudiant peut avoir
|
||||||
ce code. Vérifier votre valeur ou supprimer l'autre étudiant avec cette valeur.
|
ce code. Vérifier votre valeur ou supprimer l'autre étudiant avec cette valeur.
|
||||||
</p>
|
</p>
|
||||||
@ -845,7 +845,7 @@ def check_etud_duplicate_code(args, code_name, edit=True):
|
|||||||
|
|
||||||
log(f"*** error: code {code_name} duplique: {args[code_name]}")
|
log(f"*** error: code {code_name} duplique: {args[code_name]}")
|
||||||
|
|
||||||
raise ScoGenError(err_page)
|
raise ScoGenError(err_page, safe=True)
|
||||||
|
|
||||||
|
|
||||||
def make_etud_args(
|
def make_etud_args(
|
||||||
|
@ -508,24 +508,26 @@ def excel_simple_table(
|
|||||||
return ws.generate()
|
return ws.generate()
|
||||||
|
|
||||||
|
|
||||||
def excel_bytes_to_list(bytes_content):
|
def excel_bytes_to_list(bytes_content) -> tuple[list, list[list]]:
|
||||||
|
"Lecture d'un flux xlsx"
|
||||||
try:
|
try:
|
||||||
filelike = io.BytesIO(bytes_content)
|
filelike = io.BytesIO(bytes_content)
|
||||||
|
return _excel_to_list(filelike)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"""Le fichier xlsx attendu n'est pas lisible !
|
"""Le fichier xlsx attendu n'est pas lisible ! (1)
|
||||||
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ..)
|
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ..)
|
||||||
"""
|
"""
|
||||||
) from exc
|
) from exc
|
||||||
return _excel_to_list(filelike)
|
|
||||||
|
|
||||||
|
|
||||||
def excel_file_to_list(filename):
|
def excel_file_to_list(filelike) -> tuple[list, list[list]]:
|
||||||
|
"Lecture d'un flux xlsx"
|
||||||
try:
|
try:
|
||||||
return _excel_to_list(filename)
|
return _excel_to_list(filelike)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"""Le fichier xlsx attendu n'est pas lisible !
|
"""Le fichier xlsx attendu n'est pas lisible ! (2)
|
||||||
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...)
|
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...)
|
||||||
"""
|
"""
|
||||||
) from exc
|
) from exc
|
||||||
@ -611,7 +613,7 @@ def excel_workbook_to_list(filelike):
|
|||||||
workbook = _open_workbook(filelike)
|
workbook = _open_workbook(filelike)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"""Le fichier xlsx attendu n'est pas lisible !
|
"""Le fichier xlsx attendu n'est pas lisible ! (3)
|
||||||
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...)
|
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...)
|
||||||
"""
|
"""
|
||||||
) from exc
|
) from exc
|
||||||
|
@ -200,11 +200,11 @@ class ScoNoReferentielCompetences(ScoValueError):
|
|||||||
super().__init__(msg)
|
super().__init__(msg)
|
||||||
|
|
||||||
|
|
||||||
class ScoGenError(ScoException):
|
class ScoGenError(ScoValueError):
|
||||||
"exception avec affichage d'une page explicative ad-hoc"
|
"exception avec affichage d'une page explicative ad-hoc"
|
||||||
|
|
||||||
def __init__(self, msg=""):
|
def __init__(self, msg="", safe=False):
|
||||||
super().__init__(msg)
|
super().__init__(msg, safe=safe)
|
||||||
|
|
||||||
|
|
||||||
class AccessDenied(ScoGenError):
|
class AccessDenied(ScoGenError):
|
||||||
|
@ -478,8 +478,17 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
<a class="stdlink" style="margin-left:2em;" href="{
|
<a class="stdlink" style="margin-left:2em;" href="{
|
||||||
url_for("notes.moduleimpl_evaluation_renumber",
|
url_for("notes.moduleimpl_evaluation_renumber",
|
||||||
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
|
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
|
||||||
}">Trier par date</a>
|
}" title="Ordonner les évaluations par date">Trier par date</a>
|
||||||
"""
|
"""
|
||||||
|
bot_table_links = (
|
||||||
|
top_table_links
|
||||||
|
+ f"""
|
||||||
|
<a class="stdlink" style="margin-left:2em;" href="{
|
||||||
|
url_for("notes.moduleimpl_import_notes",
|
||||||
|
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
|
||||||
|
}" title="Charger toutles les notes via tableur">Importer les notes</a>
|
||||||
|
"""
|
||||||
|
)
|
||||||
if nb_evaluations > 0:
|
if nb_evaluations > 0:
|
||||||
H.append(
|
H.append(
|
||||||
'<div class="moduleimpl_evaluations_top_links">'
|
'<div class="moduleimpl_evaluations_top_links">'
|
||||||
@ -514,7 +523,9 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
if sem_locked:
|
if sem_locked:
|
||||||
H.append(f"""{scu.icontag("lock32_img")} semestre verrouillé""")
|
H.append(f"""{scu.icontag("lock32_img")} semestre verrouillé""")
|
||||||
elif can_edit_evals:
|
elif can_edit_evals:
|
||||||
H.append(top_table_links)
|
H.append(
|
||||||
|
f"""<div class="moduleimpl_evaluations_table_bot">{bot_table_links}</div>"""
|
||||||
|
)
|
||||||
|
|
||||||
H.append(
|
H.append(
|
||||||
f"""</td></tr>
|
f"""</td></tr>
|
||||||
|
@ -34,7 +34,7 @@ saisie_notes_tableur (formulaire)
|
|||||||
## Notes d'un semestre
|
## Notes d'un semestre
|
||||||
|
|
||||||
formsemestre_import_notes (formulaire, import_notes.j2)
|
formsemestre_import_notes (formulaire, import_notes.j2)
|
||||||
-> feuille_import_notes (génération de l'excel)
|
-> formsemestre_feuille_import_notes (génération de l'excel)
|
||||||
-> formsemestre_import_notes
|
-> formsemestre_import_notes
|
||||||
|
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ from openpyxl.styles.numbers import FORMAT_GENERAL
|
|||||||
from flask import g, render_template, request, url_for
|
from flask import g, render_template, request, url_for
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from app.models import Evaluation, FormSemestre, Identite, ScolarNews
|
from app.models import Evaluation, FormSemestre, Identite, ModuleImpl, ScolarNews
|
||||||
from app.scodoc.sco_excel import COLORS, ScoExcelSheet
|
from app.scodoc.sco_excel import COLORS, ScoExcelSheet
|
||||||
from app.scodoc import (
|
from app.scodoc import (
|
||||||
html_sco_header,
|
html_sco_header,
|
||||||
@ -61,7 +61,7 @@ from app.scodoc import (
|
|||||||
sco_saisie_notes,
|
sco_saisie_notes,
|
||||||
sco_users,
|
sco_users,
|
||||||
)
|
)
|
||||||
from app.scodoc.sco_exceptions import AccessDenied, InvalidNoteValue
|
from app.scodoc.sco_exceptions import AccessDenied, InvalidNoteValue, ScoValueError
|
||||||
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.views import ScoData
|
from app.views import ScoData
|
||||||
@ -435,12 +435,27 @@ def feuille_saisie_notes(
|
|||||||
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
||||||
|
|
||||||
|
|
||||||
def excel_feuille_import(formsemestre: FormSemestre) -> AnyStr:
|
def excel_feuille_import(
|
||||||
"""Génère feuille pour import toutes notes dans ce semestre,
|
formsemestre: FormSemestre | None = None, modimpl: ModuleImpl | None = None
|
||||||
|
) -> AnyStr:
|
||||||
|
"""Génère feuille pour import toutes notes dans ce semestre ou ce module,
|
||||||
avec une colonne par évaluation.
|
avec une colonne par évaluation.
|
||||||
Return excel data
|
Return excel data
|
||||||
"""
|
"""
|
||||||
evaluations = formsemestre.get_evaluations()
|
if not (formsemestre or modimpl):
|
||||||
|
raise ScoValueError("excel_feuille_import: missing argument")
|
||||||
|
evaluations = (
|
||||||
|
formsemestre.get_evaluations() if formsemestre else modimpl.evaluations.all()
|
||||||
|
)
|
||||||
|
if formsemestre is None:
|
||||||
|
if not evaluations:
|
||||||
|
raise ScoValueError(
|
||||||
|
"pas d'évaluations dans ce module",
|
||||||
|
dest_url=url_for(
|
||||||
|
"notes.moduleimpl_status, scodoc_dept=g.scodoc_dept, moduleimpl_id=modipl.id"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
formsemestre = evaluations[0].moduleimpl.formsemestre
|
||||||
etudiants = formsemestre.get_inscrits(include_demdef=True, order=True)
|
etudiants = formsemestre.get_inscrits(include_demdef=True, order=True)
|
||||||
rows = [{"etud": etud} for etud in etudiants]
|
rows = [{"etud": etud} for etud in etudiants]
|
||||||
# Liste les étudiants et leur note à chaque évaluation
|
# Liste les étudiants et leur note à chaque évaluation
|
||||||
@ -543,14 +558,16 @@ def generate_excel_import_notes(
|
|||||||
|
|
||||||
|
|
||||||
def do_evaluations_upload_xls(
|
def do_evaluations_upload_xls(
|
||||||
notefile,
|
notefile="",
|
||||||
comment: str = "",
|
comment: str = "",
|
||||||
evaluation: Evaluation | None = None,
|
evaluation: Evaluation | None = None,
|
||||||
formsemestre: FormSemestre | None = None,
|
formsemestre: FormSemestre | None = None,
|
||||||
|
modimpl: ModuleImpl | None = None,
|
||||||
) -> tuple[bool, str]:
|
) -> tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Soumission d'un fichier XLS (evaluation_id, notefile)
|
Soumission d'un fichier XLS (evaluation_id, notefile)
|
||||||
soit dans le formsemestre (import multi-eval)
|
soit dans le formsemestre (import multi-eval)
|
||||||
|
soit dans toules les évaluations du modimpl
|
||||||
soit dans une seule évaluation
|
soit dans une seule évaluation
|
||||||
return:
|
return:
|
||||||
ok: bool
|
ok: bool
|
||||||
@ -563,7 +580,11 @@ def do_evaluations_upload_xls(
|
|||||||
|
|
||||||
# Lecture des évaluations ids
|
# Lecture des évaluations ids
|
||||||
row_title_idx, evaluations, evaluations_col_idx = _get_sheet_evaluations(
|
row_title_idx, evaluations, evaluations_col_idx = _get_sheet_evaluations(
|
||||||
rows, evaluation=evaluation, formsemestre=formsemestre, diag=diag
|
rows,
|
||||||
|
evaluation=evaluation,
|
||||||
|
formsemestre=formsemestre,
|
||||||
|
modimpl=modimpl,
|
||||||
|
diag=diag,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Vérification des permissions (admin, resp. formation, responsable_id, ens)
|
# Vérification des permissions (admin, resp. formation, responsable_id, ens)
|
||||||
@ -591,12 +612,26 @@ def do_evaluations_upload_xls(
|
|||||||
modules_str = ", ".join(
|
modules_str = ", ".join(
|
||||||
[evaluation.moduleimpl.module.code for evaluation in evaluations]
|
[evaluation.moduleimpl.module.code for evaluation in evaluations]
|
||||||
)
|
)
|
||||||
status_url = url_for(
|
status_url = (
|
||||||
"notes.formsemestre_status",
|
url_for(
|
||||||
scodoc_dept=g.scodoc_dept,
|
"notes.formsemestre_status",
|
||||||
formsemestre_id=formsemestre.id,
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
formsemestre_id=formsemestre.id,
|
||||||
|
)
|
||||||
|
if formsemestre
|
||||||
|
else (
|
||||||
|
url_for(
|
||||||
|
"notes.moduleimpl_status",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
moduleimpl_id=modimpl.id,
|
||||||
|
)
|
||||||
|
if modimpl
|
||||||
|
else ""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
obj_id = (
|
||||||
|
formsemestre.id if formsemestre else (modimpl.id if modimpl else None)
|
||||||
)
|
)
|
||||||
obj_id = formsemestre.id
|
|
||||||
else:
|
else:
|
||||||
modules_str = (
|
modules_str = (
|
||||||
evaluation.moduleimpl.module.titre or evaluation.moduleimpl.module.code
|
evaluation.moduleimpl.module.titre or evaluation.moduleimpl.module.code
|
||||||
@ -862,6 +897,7 @@ def _get_sheet_evaluations(
|
|||||||
rows: list[list[str]],
|
rows: list[list[str]],
|
||||||
evaluation: Evaluation | None = None,
|
evaluation: Evaluation | None = None,
|
||||||
formsemestre: FormSemestre | None = None,
|
formsemestre: FormSemestre | None = None,
|
||||||
|
modimpl: ModuleImpl | None = None,
|
||||||
diag: list[str] = None,
|
diag: list[str] = None,
|
||||||
) -> tuple[int, list[Evaluation], dict[int, int]]:
|
) -> tuple[int, list[Evaluation], dict[int, int]]:
|
||||||
"""
|
"""
|
||||||
@ -869,7 +905,8 @@ def _get_sheet_evaluations(
|
|||||||
diag: liste dans laquelle accumuler les messages d'erreur
|
diag: liste dans laquelle accumuler les messages d'erreur
|
||||||
evaluation (optionnel): l'évaluation que l'on cherche à remplir (pour feuille mono-évaluation)
|
evaluation (optionnel): l'évaluation que l'on cherche à remplir (pour feuille mono-évaluation)
|
||||||
formsemestre (optionnel): le formsemestre dans lequel sont les évaluations à remplir
|
formsemestre (optionnel): le formsemestre dans lequel sont les évaluations à remplir
|
||||||
formsemestre ou evaluation doivent être indiqués.
|
modimpl (optionel): le moduleimpl dans lequel sont les évaluations à remplir
|
||||||
|
formsemestre ou evaluation ou modimpl doivent être indiqués.
|
||||||
|
|
||||||
Résultat:
|
Résultat:
|
||||||
row_title_idx: l'indice (à partir de 0) de la ligne TITRE (après laquelle commencent les notes)
|
row_title_idx: l'indice (à partir de 0) de la ligne TITRE (après laquelle commencent les notes)
|
||||||
@ -896,7 +933,15 @@ def _get_sheet_evaluations(
|
|||||||
if evaluation is None:
|
if evaluation is None:
|
||||||
diag.append(f"""Erreur: l'évaluation {evaluation_id} n'existe pas""")
|
diag.append(f"""Erreur: l'évaluation {evaluation_id} n'existe pas""")
|
||||||
raise InvalidNoteValue()
|
raise InvalidNoteValue()
|
||||||
if evaluation.moduleimpl.formsemestre_id != formsemestre.id:
|
if (
|
||||||
|
formsemestre
|
||||||
|
and evaluation.moduleimpl.formsemestre_id != formsemestre.id
|
||||||
|
):
|
||||||
|
diag.append(
|
||||||
|
f"""Erreur: l'évaluation {evaluation_id} n'existe pas dans ce semestre"""
|
||||||
|
)
|
||||||
|
raise InvalidNoteValue()
|
||||||
|
if modimpl and evaluation.moduleimpl.id != modimpl.id:
|
||||||
diag.append(
|
diag.append(
|
||||||
f"""Erreur: l'évaluation {evaluation_id} n'existe pas dans ce semestre"""
|
f"""Erreur: l'évaluation {evaluation_id} n'existe pas dans ce semestre"""
|
||||||
)
|
)
|
||||||
@ -1014,7 +1059,7 @@ def saisie_notes_tableur(evaluation_id: int, group_ids=()):
|
|||||||
args = scu.get_request_args()
|
args = scu.get_request_args()
|
||||||
evaluation = Evaluation.get_evaluation(args["evaluation_id"])
|
evaluation = Evaluation.get_evaluation(args["evaluation_id"])
|
||||||
ok, diagnostic_msg = do_evaluations_upload_xls(
|
ok, diagnostic_msg = do_evaluations_upload_xls(
|
||||||
args["notefile"], evaluation=evaluation, comment=args["comment"]
|
notefile=args["notefile"], evaluation=evaluation, comment=args["comment"]
|
||||||
)
|
)
|
||||||
if ok:
|
if ok:
|
||||||
H.append(
|
H.append(
|
||||||
@ -1124,16 +1169,23 @@ def saisie_notes_tableur(evaluation_id: int, group_ids=()):
|
|||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_import_notes(formsemestre: FormSemestre, notefile, comment: str):
|
def formsemestre_import_notes(
|
||||||
"""Importation de notes dans plusieurs évaluations du semestre"""
|
formsemestre: FormSemestre | None = None,
|
||||||
|
modimpl: ModuleImpl | None = None,
|
||||||
|
notefile="",
|
||||||
|
comment: str = "",
|
||||||
|
):
|
||||||
|
"""Importation de notes dans plusieurs évaluations
|
||||||
|
du formsemestre ou du modimpl"""
|
||||||
ok, diagnostic_msg = do_evaluations_upload_xls(
|
ok, diagnostic_msg = do_evaluations_upload_xls(
|
||||||
notefile, formsemestre=formsemestre, comment=comment
|
notefile=notefile, formsemestre=formsemestre, modimpl=modimpl, comment=comment
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"formsemestre/import_notes_after.j2",
|
"formsemestre/import_notes_after.j2",
|
||||||
comment=comment,
|
comment=comment,
|
||||||
ok=ok,
|
ok=ok,
|
||||||
diagnostic_msg=diagnostic_msg,
|
diagnostic_msg=diagnostic_msg,
|
||||||
sco=ScoData(formsemestre=formsemestre),
|
modimpl=modimpl,
|
||||||
|
sco=ScoData(formsemestre=formsemestre or modimpl.formsemestre),
|
||||||
title="Importation des notes",
|
title="Importation des notes",
|
||||||
)
|
)
|
||||||
|
@ -2168,6 +2168,11 @@ span.moduleimpl_abs_link {
|
|||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.moduleimpl_evaluations_table_bot {
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
table.moduleimpl_evaluations {
|
table.moduleimpl_evaluations {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-spacing: 0px;
|
border-spacing: 0px;
|
||||||
|
@ -12,11 +12,27 @@ div.vspace {
|
|||||||
|
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
||||||
<h2>Import de notes dans les évaluations du semestre</h2>
|
<h2>Import de notes dans les évaluations du
|
||||||
|
{% if modimpl %}
|
||||||
|
module
|
||||||
|
{% else %}
|
||||||
|
semestre
|
||||||
|
{% endif %}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{% if modimpl %}
|
||||||
|
<div class="help">
|
||||||
|
Cette page permet d'importer des notes dans tout ou partie des évaluations du module.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Il y a <a class="stdlink" href="{{
|
||||||
|
url_for('notes.moduleimpl_status', scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id )
|
||||||
|
}}">{{ evaluations | length }} évaluations définies dans le module {{modimpl.module.code}}</a>.
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
<div class="help">
|
<div class="help">
|
||||||
Cette page permet d'importer des notes dans tout ou partie des évaluations du semestre.
|
Cette page permet d'importer des notes dans tout ou partie des évaluations du semestre.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -24,12 +40,15 @@ Cette page permet d'importer des notes dans tout ou partie des évaluations du s
|
|||||||
url_for('notes.evaluations_recap', scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id )
|
url_for('notes.evaluations_recap', scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id )
|
||||||
}}">{{ evaluations | length }} évaluations</a> définies dans ce semestre.
|
}}">{{ evaluations | length }} évaluations</a> définies dans ce semestre.
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="saisienote_etape1">
|
<div class="saisienote_etape1">
|
||||||
<span class="titredivsaisienote">Étape 1 : </span>
|
<span class="titredivsaisienote">Étape 1 : </span>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a class="stdlink" href="{{
|
<li><a class="stdlink" href="{{
|
||||||
url_for( 'notes.feuille_import_notes', scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id )
|
url_for( 'notes.moduleimpl_feuille_import_notes', scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id )
|
||||||
|
if modimpl else
|
||||||
|
url_for( 'notes.formsemestre_feuille_import_notes', scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id )
|
||||||
}}" id="lnk_feuille_saisie">
|
}}" id="lnk_feuille_saisie">
|
||||||
obtenir le fichier tableur à remplir
|
obtenir le fichier tableur à remplir
|
||||||
</a>
|
</a>
|
||||||
|
@ -18,7 +18,13 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
||||||
<h2>Import de notes dans les évaluations du semestre</h2>
|
<h2>Import de notes dans les évaluations du
|
||||||
|
{% if modimpl %}
|
||||||
|
module
|
||||||
|
{% else %}
|
||||||
|
semestre
|
||||||
|
{% endif %}
|
||||||
|
</h2>
|
||||||
|
|
||||||
<div class="scobox {{ 'success' if ok else 'failure' }}">
|
<div class="scobox {{ 'success' if ok else 'failure' }}">
|
||||||
<div class="scobox-title">
|
<div class="scobox-title">
|
||||||
@ -36,6 +42,23 @@
|
|||||||
<div class="scobox">
|
<div class="scobox">
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
{% if modimpl %}
|
||||||
|
<li><a class="stdlink"
|
||||||
|
href="{{url_for('notes.moduleimpl_status',
|
||||||
|
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id,
|
||||||
|
)}}">
|
||||||
|
{{modimpl.module.type_name()}} {{modimpl.module.code}} {{modimpl.module.titre_str()}}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li><a class="stdlink"
|
||||||
|
href="{{url_for('notes.evaluation_listenotes',
|
||||||
|
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id,
|
||||||
|
)}}">
|
||||||
|
Lister les notes de {{modimpl.module.code}}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<li><a class="stdlink"
|
<li><a class="stdlink"
|
||||||
href="{{url_for('notes.formsemestre_recapcomplet',
|
href="{{url_for('notes.formsemestre_recapcomplet',
|
||||||
scodoc_dept=g.scodoc_dept, formsemestre_id=sco.formsemestre.id,
|
scodoc_dept=g.scodoc_dept, formsemestre_id=sco.formsemestre.id,
|
||||||
@ -43,12 +66,14 @@
|
|||||||
Tableau de <em>toutes</em> les notes du semestre
|
Tableau de <em>toutes</em> les notes du semestre
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% if sco.formsemestre %}
|
||||||
<li><a class="stdlink"
|
<li><a class="stdlink"
|
||||||
href="{{url_for('notes.formsemestre_import_notes',
|
href="{{url_for('notes.formsemestre_import_notes',
|
||||||
scodoc_dept=g.scodoc_dept, formsemestre_id=sco.formsemestre.id)}}">
|
scodoc_dept=g.scodoc_dept, formsemestre_id=sco.formsemestre.id)}}">
|
||||||
Importer d'autres notes
|
Importer d'autres notes
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1842,19 +1842,57 @@ sco_publish(
|
|||||||
@bp.route("/formsemestre_import_notes/<int:formsemestre_id>", methods=["GET", "POST"])
|
@bp.route("/formsemestre_import_notes/<int:formsemestre_id>", methods=["GET", "POST"])
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView) # controle contextuel
|
@permission_required(Permission.ScoView) # controle contextuel
|
||||||
def formsemestre_import_notes(formsemestre_id: int):
|
def formsemestre_import_notes(formsemestre_id: int | None = None):
|
||||||
"""Import via excel des notes de toutes les évals d'un semestre"""
|
"Import via excel des notes de toutes les évals d'un semestre."
|
||||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
return _formsemestre_or_modimpl_import_notes(formsemestre_id=formsemestre_id)
|
||||||
dest_url = url_for(
|
|
||||||
"notes.formsemestre_status",
|
|
||||||
scodoc_dept=g.scodoc_dept,
|
@bp.route(
|
||||||
formsemestre_id=formsemestre.id,
|
"/moduleimpl_import_notes/<int:moduleimpl_id>",
|
||||||
|
methods=["GET", "POST"],
|
||||||
|
)
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView) # controle contextuel
|
||||||
|
def moduleimpl_import_notes(moduleimpl_id: int | None = None):
|
||||||
|
"Import via excel des notes de toutes les évals d'un module."
|
||||||
|
return _formsemestre_or_modimpl_import_notes(moduleimpl_id=moduleimpl_id)
|
||||||
|
|
||||||
|
|
||||||
|
def _formsemestre_or_modimpl_import_notes(
|
||||||
|
formsemestre_id: int | None = None, moduleimpl_id: int | None = None
|
||||||
|
):
|
||||||
|
"""Import via excel des notes de toutes les évals d'un semestre.
|
||||||
|
Ou, si moduleimpl_import_notes, toutes les évals de ce module.
|
||||||
|
"""
|
||||||
|
formsemestre = (
|
||||||
|
FormSemestre.get_formsemestre(formsemestre_id)
|
||||||
|
if formsemestre_id is not None
|
||||||
|
else None
|
||||||
)
|
)
|
||||||
if not formsemestre.est_chef_or_diretud():
|
modimpl = (
|
||||||
|
ModuleImpl.get_modimpl(moduleimpl_id) if moduleimpl_id is not None else None
|
||||||
|
)
|
||||||
|
if not (formsemestre or modimpl):
|
||||||
|
raise ScoValueError("paramètre manquant")
|
||||||
|
dest_url = (
|
||||||
|
url_for(
|
||||||
|
"notes.moduleimpl_status",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
moduleimpl_id=modimpl.id,
|
||||||
|
)
|
||||||
|
if modimpl
|
||||||
|
else url_for(
|
||||||
|
"notes.formsemestre_status",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
formsemestre_id=formsemestre.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if formsemestre and not formsemestre.est_chef_or_diretud():
|
||||||
|
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
||||||
|
if modimpl and not modimpl.can_edit_notes(current_user):
|
||||||
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
|
||||||
|
|
||||||
class ImportForm(FlaskForm):
|
class ImportForm(FlaskForm):
|
||||||
evaluation_id = HiddenField("formsemestre_id", default=formsemestre.id)
|
|
||||||
notefile = FileField(
|
notefile = FileField(
|
||||||
"Fichier d'import",
|
"Fichier d'import",
|
||||||
validators=[
|
validators=[
|
||||||
@ -1872,30 +1910,51 @@ def formsemestre_import_notes(formsemestre_id: int):
|
|||||||
comment = form.comment.data
|
comment = form.comment.data
|
||||||
#
|
#
|
||||||
return sco_saisie_excel.formsemestre_import_notes(
|
return sco_saisie_excel.formsemestre_import_notes(
|
||||||
formsemestre, notefile, comment
|
formsemestre=formsemestre,
|
||||||
|
modimpl=modimpl,
|
||||||
|
notefile=notefile,
|
||||||
|
comment=comment,
|
||||||
)
|
)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"formsemestre/import_notes.j2",
|
"formsemestre/import_notes.j2",
|
||||||
evaluations=formsemestre.get_evaluations(),
|
evaluations=(
|
||||||
|
formsemestre.get_evaluations()
|
||||||
|
if formsemestre
|
||||||
|
else modimpl.evaluations.all()
|
||||||
|
),
|
||||||
form=form,
|
form=form,
|
||||||
formsemestre=formsemestre,
|
formsemestre=formsemestre,
|
||||||
|
modimpl=modimpl,
|
||||||
title="Importation des notes",
|
title="Importation des notes",
|
||||||
sco=ScoData(formsemestre=formsemestre),
|
sco=ScoData(formsemestre=formsemestre),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/feuille_import_notes/<int:formsemestre_id>")
|
@bp.route("/formsemestre_feuille_import_notes/<int:formsemestre_id>")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
def feuille_import_notes(formsemestre_id: int):
|
def formsemestre_feuille_import_notes(formsemestre_id: int):
|
||||||
"""Feuille excel pour importer les notes de toutes les évaluations du semestre"""
|
"""Feuille excel pour importer les notes de toutes les évaluations du semestre"""
|
||||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||||
xls = sco_saisie_excel.excel_feuille_import(formsemestre)
|
xls = sco_saisie_excel.excel_feuille_import(formsemestre=formsemestre)
|
||||||
filename = scu.sanitize_filename(formsemestre.titre_annee())
|
filename = scu.sanitize_filename(formsemestre.titre_annee())
|
||||||
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/moduleimpl_feuille_import_notes/<int:moduleimpl_id>")
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def moduleimpl_feuille_import_notes(moduleimpl_id: int):
|
||||||
|
"""Feuille excel pour importer les notes de toutes les évaluations du modimpl"""
|
||||||
|
modimpl = ModuleImpl.get_modimpl(moduleimpl_id)
|
||||||
|
xls = sco_saisie_excel.excel_feuille_import(modimpl=modimpl)
|
||||||
|
filename = scu.sanitize_filename(
|
||||||
|
f"{modimpl.module.code} {modimpl.formsemestre.annee_scolaire_str()}"
|
||||||
|
)
|
||||||
|
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
||||||
|
|
||||||
|
|
||||||
# --- Bulletins
|
# --- Bulletins
|
||||||
@bp.route("/formsemestre_bulletins_pdf")
|
@bp.route("/formsemestre_bulletins_pdf")
|
||||||
@scodoc
|
@scodoc
|
||||||
|
Loading…
Reference in New Issue
Block a user