diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py
index 9815b9fd4a..6b832a8821 100644
--- a/app/models/formsemestre.py
+++ b/app/models/formsemestre.py
@@ -257,6 +257,11 @@ class FormSemestre(db.Model):
d["etapes_apo_str"] = self.etapes_apo_str()
return d
+ def flip_lock(self):
+ """Flip etat (lock)"""
+ self.etat = not self.etat
+ db.session.add(self)
+
def get_parcours_apc(self) -> list[ApcParcours]:
"""Liste des parcours proposés par ce semestre.
Si aucun n'est coché et qu'il y a un référentiel, tous ceux du référentiel.
diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py
index 96c85d69aa..7230bffa13 100644
--- a/app/scodoc/sco_bulletins.py
+++ b/app/scodoc/sco_bulletins.py
@@ -908,7 +908,8 @@ def formsemestre_bulletinetud(
)[0]
if format not in {"html", "pdfmail"}:
filename = scu.bul_filename(formsemestre, etud, format)
- return scu.send_file(bulletin, filename, mime=scu.get_mime_suffix(format)[0])
+ mime, suffix = scu.get_mime_suffix(format)
+ return scu.send_file(bulletin, filename, mime=mime, suffix=suffix)
elif format == "pdfmail":
return ""
H = [
diff --git a/app/scodoc/sco_cost_formation.py b/app/scodoc/sco_cost_formation.py
index 09d1e12290..16429881b8 100644
--- a/app/scodoc/sco_cost_formation.py
+++ b/app/scodoc/sco_cost_formation.py
@@ -32,12 +32,12 @@
"""
from flask import request
-import app.scodoc.sco_utils as scu
+from app.models import FormSemestre
from app.scodoc.gen_tables import GenTable
from app.scodoc import sco_formsemestre
from app.scodoc import sco_moduleimpl
-from app.scodoc import sco_formsemestre_status
from app.scodoc import sco_preferences
+import app.scodoc.sco_utils as scu
import sco_version
@@ -57,37 +57,35 @@ def formsemestre_table_estim_cost(
peut conduire à une sur-estimation du coût s'il y a des modules optionnels
(dans ce cas, retoucher le tableau excel exporté).
"""
- sem = sco_formsemestre.get_formsemestre(formsemestre_id)
- sco_formsemestre_status.fill_formsemestre(sem)
- Mlist = sco_moduleimpl.moduleimpl_withmodule_list(formsemestre_id=formsemestre_id)
- T = []
- for M in Mlist:
- Mod = M["module"]
- T.append(
+ formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
+
+ rows = []
+ for modimpl in formsemestre.modimpls:
+ rows.append(
{
- "code": Mod["code"] or "",
- "titre": Mod["titre"],
- "heures_cours": Mod["heures_cours"],
- "heures_td": Mod["heures_td"] * n_group_td,
- "heures_tp": Mod["heures_tp"] * n_group_tp,
+ "code": modimpl.module.code or "",
+ "titre": modimpl.module.titre,
+ "heures_cours": modimpl.module.heures_cours,
+ "heures_td": modimpl.module.heures_td * n_group_td,
+ "heures_tp": modimpl.module.heures_tp * n_group_tp,
}
)
# calcul des heures:
- for t in T:
+ for t in rows:
t["HeqTD"] = (
t["heures_td"] + coef_cours * t["heures_cours"] + coef_tp * t["heures_tp"]
)
- sum_cours = sum([t["heures_cours"] for t in T])
- sum_td = sum([t["heures_td"] for t in T])
- sum_tp = sum([t["heures_tp"] for t in T])
+ sum_cours = sum([t["heures_cours"] for t in rows])
+ sum_td = sum([t["heures_td"] for t in rows])
+ sum_tp = sum([t["heures_tp"] for t in rows])
sum_heqtd = sum_td + coef_cours * sum_cours + coef_tp * sum_tp
- assert abs(sum([t["HeqTD"] for t in T]) - sum_heqtd) < 0.01, "%s != %s" % (
- sum([t["HeqTD"] for t in T]),
+ assert abs(sum([t["HeqTD"] for t in rows]) - sum_heqtd) < 0.01, "%s != %s" % (
+ sum([t["HeqTD"] for t in rows]),
sum_heqtd,
)
- T.append(
+ rows.append(
{
"code": "TOTAL SEMESTRE",
"heures_cours": sum_cours,
@@ -117,13 +115,15 @@ def formsemestre_table_estim_cost(
"heures_tp",
"HeqTD",
),
- rows=T,
+ rows=rows,
html_sortable=True,
preferences=sco_preferences.SemPreferences(formsemestre_id),
html_class="table_leftalign table_listegroupe",
xls_before_table=[
- ["%(titre)s %(num_sem)s %(modalitestr)s" % sem],
- ["Formation %(titre)s version %(version)s" % sem["formation"]],
+ [formsemestre.titre_annee()],
+ [
+ f"Formation {formsemestre.formation.titre} version {formsemestre.formation.version}"
+ ],
[],
["", "TD", "TP"],
["Nombre de groupes", n_group_td, n_group_tp],
@@ -140,10 +140,8 @@ def formsemestre_table_estim_cost(
(dans ce cas, retoucher le tableau excel exporté).
""",
- origin="Généré par %s le " % sco_version.SCONAME
- + scu.timedate_human_repr()
- + "",
- filename="EstimCout-S%s" % sem["semestre_id"],
+ origin=f"""Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}""",
+ filename=f"EstimCout-S{formsemestre.semestre_id}",
)
return tab
diff --git a/app/scodoc/sco_formations.py b/app/scodoc/sco_formations.py
index 84a6039be6..29103d94c9 100644
--- a/app/scodoc/sco_formations.py
+++ b/app/scodoc/sco_formations.py
@@ -485,7 +485,7 @@ def formation_list_table() -> GenTable:
)
+ f""", ajouter
diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py
index 584f591adb..3280b1be50 100644
--- a/app/scodoc/sco_formsemestre_edit.py
+++ b/app/scodoc/sco_formsemestre_edit.py
@@ -1659,20 +1659,6 @@ def formsemestre_edit_options(formsemestre_id):
return sco_preferences.SemPreferences(formsemestre_id).edit(categories=["bul"])
-def formsemestre_change_lock(formsemestre_id) -> None:
- """Change etat (verrouille si ouvert, déverrouille si fermé)
- nota: etat (1 ouvert, 0 fermé)
- """
- ok, err = sco_permissions_check.check_access_diretud(formsemestre_id)
- if not ok:
- return err
- sem = sco_formsemestre.get_formsemestre(formsemestre_id)
- etat = not sem["etat"]
-
- args = {"formsemestre_id": formsemestre_id, "etat": etat}
- sco_formsemestre.do_formsemestre_edit(args)
-
-
def formsemestre_change_publication_bul(
formsemestre_id, dialog_confirmed=False, redirect=True
):
diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py
index d3ac77400c..32478d0b52 100644
--- a/app/scodoc/sco_formsemestre_status.py
+++ b/app/scodoc/sco_formsemestre_status.py
@@ -200,7 +200,7 @@ def formsemestre_status_menubar(formsemestre: FormSemestre) -> str:
},
{
"title": change_lock_msg,
- "endpoint": "notes.formsemestre_change_lock",
+ "endpoint": "notes.formsemestre_flip_lock",
"args": {"formsemestre_id": formsemestre_id},
"enabled": has_perm_change_sem,
"helpmsg": "",
@@ -546,59 +546,6 @@ def formsemestre_page_title(formsemestre_id=None):
)
-def fill_formsemestre(sem):
- """Add some useful fields to help display formsemestres"""
- sem["notes_url"] = scu.NotesURL()
- formsemestre_id = sem["formsemestre_id"]
- if not sem["etat"]:
- sem[
- "locklink"
- ] = f"""{scu.icontag("lock_img", border="0", title="Semestre verrouillé")}"""
- else:
- sem["locklink"] = ""
- if sco_preferences.get_preference("bul_display_publication", formsemestre_id):
- if sem["bul_hide_xml"]:
- eyeicon = scu.icontag("hide_img", border="0", title="Bulletins NON publiés")
- else:
- eyeicon = scu.icontag("eye_img", border="0", title="Bulletins publiés")
- sem[
- "eyelink"
- ] = f"""{eyeicon}"""
- else:
- sem["eyelink"] = ""
- sem["formation"] = Formation.query.get_or_404(sem["formation_id"]).to_dict(
- with_departement=False
- )
- parcours = codes_cursus.get_cursus_from_code(F["type_parcours"])
- if sem["semestre_id"] != -1:
- sem["num_sem"] = f""", {parcours.SESSION_NAME} {sem["semestre_id"]}"""
- else:
- sem["num_sem"] = "" # formation sans semestres
- if sem["modalite"]:
- sem["modalitestr"] = f""" en {sem["modalite"]}"""
- else:
- sem["modalitestr"] = ""
-
- sem["etape_apo_str"] = "Code étape Apogée: " + (
- sco_formsemestre.formsemestre_etape_apo_str(sem) or "Pas de code étape"
- )
-
- inscrits = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
- args={"formsemestre_id": formsemestre_id}
- )
- sem["nbinscrits"] = len(inscrits)
- uresps = [
- sco_users.user_info(responsable_id) for responsable_id in sem["responsables"]
- ]
- sem["resp"] = ", ".join([u["prenomnom"] for u in uresps])
- sem["nomcomplet"] = ", ".join([u["nomcomplet"] for u in uresps])
-
-
# Description du semestre sous forme de table exportable
def formsemestre_description_table(
formsemestre_id: int, with_evals=False, with_parcours=False
@@ -645,7 +592,7 @@ def formsemestre_description_table(
titles["publish_incomplete_str"] = "Toujours utilisée"
title = f"{parcours.SESSION_NAME.capitalize()} {formsemestre.titre_mois()}"
- R = []
+ rows = []
sum_coef = 0
sum_ects = 0
last_ue_id = None
@@ -671,7 +618,7 @@ def formsemestre_description_table(
if use_ue_coefs:
ue_info["Coef."] = ue.coefficient
ue_info["Coef._class"] = "ue_coef"
- R.append(ue_info)
+ rows.append(ue_info)
mod_inscrits = sco_moduleimpl.do_moduleimpl_inscription_list(
moduleimpl_id=modimpl.id
@@ -713,14 +660,15 @@ def formsemestre_description_table(
sorted([pa.code for pa in modimpl.module.parcours])
)
- R.append(l)
+ rows.append(l)
if with_evals:
# Ajoute lignes pour evaluations
evals = nt.get_mod_evaluation_etat_list(modimpl.id)
evals.reverse() # ordre chronologique
# Ajoute etat:
- for e in evals:
+ for eval_dict in evals:
+ e = eval_dict.copy()
e["_jour_order"] = e["jour"].isoformat()
e["jour"] = e["jour"].strftime("%d/%m/%Y") if e["jour"] else ""
e["UE"] = l["UE"]
@@ -749,14 +697,14 @@ def formsemestre_description_table(
e[f"_ue_{ue_id}_class"] = "poids"
e[f"_ue_{ue_id}_help"] = "poids vers l'UE"
- R += evals
+ rows += evals
sums = {"_css_row_class": "moyenne sortbottom", "ects": sum_ects, "Coef.": sum_coef}
- R.append(sums)
+ rows.append(sums)
return GenTable(
columns_ids=columns_ids,
- rows=R,
+ rows=rows,
titles=titles,
origin=f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}",
caption=title,
diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py
index 011a570850..f03bab04c0 100644
--- a/app/scodoc/sco_recapcomplet.py
+++ b/app/scodoc/sco_recapcomplet.py
@@ -294,9 +294,8 @@ def _formsemestre_recapcomplet_to_file(
include_evaluations=include_evaluations,
filename=filename,
)
- return scu.send_file(
- data, filename=filename, mime=scu.get_mime_suffix(tabformat)
- )
+ mime, suffix = scu.get_mime_suffix(tabformat)
+ return scu.send_file(data, filename=filename, mime=mime, suffix=suffix)
elif tabformat == "xml":
data = gen_formsemestre_recapcomplet_xml(
formsemestre.id,
diff --git a/app/static/css/gt_table.css b/app/static/css/gt_table.css
index 90c9bf08c5..f4b644df4a 100644
--- a/app/static/css/gt_table.css
+++ b/app/static/css/gt_table.css
@@ -10,6 +10,7 @@
table.dataTable {
width: 100%;
margin: 0 auto;
+ margin-left: 0px;
clear: both;
border-collapse: separate;
border-spacing: 0;
@@ -643,10 +644,12 @@ table.dataTable.order-column.stripe.hover tbody tr.even:hover td.sorting_1 {
/* Reglage largeur de la table */
table.dataTable.gt_table {
width: auto;
+ margin-left: 32px;
+ margin-top: 8px;
padding-right: 5px;
}
-/* Tables non centrées */
+/* Tables non centrées (inutile) */
table.dataTable.gt_table.gt_left {
margin-left: 16px;
}
\ No newline at end of file
diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css
index 1a88fa5444..9676f89e0c 100644
--- a/app/static/css/scodoc.css
+++ b/app/static/css/scodoc.css
@@ -2069,9 +2069,11 @@ table#formation_list_table tr.gt_hl {
table.formation_list_table td.buttons {
white-space: nowrap;
}
+
table.formation_list_table td.buttons a {
margin-left: 8px;
}
+
table.formation_list_table td.buttons span.but_placeholder {
display: inline-block;
width: 15px;
@@ -4036,7 +4038,8 @@ div.table_recap {
}
*/
-div.table_recap table.table_recap {
+div.table_recap table.table_recap,
+div.evaluations_recap table.evaluations_recap {
width: auto;
margin-left: 0px;
/* font-family: Consolas, monaco, monospace; */
@@ -4230,9 +4233,10 @@ table.table_recap th.col_res {
border-right: 1px dashed green;
border-left: 1px dashed green;
}
+
table.table_recap td.abs,
table.table_recap th.abs {
- color:rgb(80, 0, 0);
+ color: rgb(80, 0, 0);
border-right: 1px dashed green;
border-left: 1px dashed green;
}
diff --git a/app/templates/formsemestre_header.j2 b/app/templates/formsemestre_header.j2
index fae42f00ff..a768582329 100644
--- a/app/templates/formsemestre_header.j2
+++ b/app/templates/formsemestre_header.j2
@@ -21,7 +21,7 @@
title="{{sco.sem.responsables_str(abbrev_prenom=False)}}">{{sco.sem.responsables_str()}}
{{sco.sem.inscriptions|length}} inscrits{% if
- not sco.sem.etat %}{{sco.scu.icontag("lock_img", border="0", title="Semestre
verrouillé")|safe}}{% endif %}
{% if sco.prefs["bul_display_publication"] %}
diff --git a/app/templates/formsemestre_page_title.j2 b/app/templates/formsemestre_page_title.j2
index 14c7f6ea51..95774dae41 100644
--- a/app/templates/formsemestre_page_title.j2
+++ b/app/templates/formsemestre_page_title.j2
@@ -21,7 +21,7 @@
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id)
}}">{{formsemestre.etuds_inscriptions|length}} inscrits
{%-if not formsemestre.etat -%}
- {{
scu.icontag("lock_img", border="0", title="Semestre verrouillé")|safe
}}
diff --git a/app/views/notes.py b/app/views/notes.py
index 545ba9f5b7..2bf9b17238 100644
--- a/app/views/notes.py
+++ b/app/views/notes.py
@@ -820,20 +820,22 @@ sco_publish(
)
-@bp.route("/formsemestre_change_lock", methods=["GET", "POST"])
+@bp.route("/formsemestre_flip_lock", methods=["GET", "POST"])
@scodoc
-@permission_required(Permission.ScoView) # acces vérifié dans la fonction
+@permission_required(Permission.ScoView) # acces vérifié dans la vue
@scodoc7func
-def formsemestre_change_lock(formsemestre_id, dialog_confirmed=False):
+def formsemestre_flip_lock(formsemestre_id, dialog_confirmed=False):
"Changement de l'état de verrouillage du semestre"
-
+ formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
+ dest_url = url_for(
+ "notes.formsemestre_status",
+ scodoc_dept=g.scodoc_dept,
+ formsemestre_id=formsemestre.id,
+ )
+ if not formsemestre.est_chef_or_diretud():
+ raise ScoPermissionDenied("opération non autorisée", dest_url=dest_url)
if not dialog_confirmed:
- sem = sco_formsemestre.get_formsemestre(formsemestre_id)
- etat = not sem["etat"]
- if etat:
- msg = "déverrouillage"
- else:
- msg = "verrouillage"
+ msg = "verrouillage" if formsemestre.etat else "déverrouillage"
return scu.confirm_dialog(
f"Confirmer le {msg} du semestre ?
",
helpmsg="""Les notes d'un semestre verrouillé ne peuvent plus être modifiées.
@@ -843,23 +845,14 @@ def formsemestre_change_lock(formsemestre_id, dialog_confirmed=False):
Le programme d'une formation qui a un semestre verrouillé ne peut plus être modifié.
""",
dest_url="",
- cancel_url=url_for(
- "notes.formsemestre_status",
- scodoc_dept=g.scodoc_dept,
- formsemestre_id=formsemestre_id,
- ),
+ cancel_url=dest_url,
parameters={"formsemestre_id": formsemestre_id},
)
- sco_formsemestre_edit.formsemestre_change_lock(formsemestre_id)
+ formsemestre.flip_lock()
+ db.session.commit()
- return flask.redirect(
- url_for(
- "notes.formsemestre_status",
- scodoc_dept=g.scodoc_dept,
- formsemestre_id=formsemestre_id,
- )
- )
+ return flask.redirect(dest_url)
sco_publish(
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
index a0291f0699..dc5a532f1a 100644
--- a/tests/unit/__init__.py
+++ b/tests/unit/__init__.py
@@ -1 +1,17 @@
-# Unit tests
+# ScoDoc Unit Tests
+
+"""Set of unit tests for ScoDoc
+"""
+
+
+def call_view(view_function, *args, **kwargs):
+ """Undecorate a view and call it directly."""
+ # On a 3 décorateurs: @scodoc, @permission_required, @scodoc7func
+ func = (
+ view_function.__closure__[0]
+ .cell_contents.__closure__[0]
+ .cell_contents.__closure__[0]
+ .cell_contents
+ )
+ assert func
+ return func(*args, **kwargs)
diff --git a/tests/unit/test_but_jury.py b/tests/unit/test_but_jury.py
index e4ea40e0e2..14d0343452 100644
--- a/tests/unit/test_but_jury.py
+++ b/tests/unit/test_but_jury.py
@@ -42,7 +42,7 @@ def test_but_jury_GB(test_client):
app.set_sco_dept(DEPT)
# Construit la base de test GB une seule fois
# puis lance les tests de jury
- doc = yaml_setup.setup_from_yaml("tests/unit/cursus_but_gb.yaml")
+ doc = yaml_setup.setup_from_yaml("tests/ressources/yaml/cursus_but_gb.yaml")
# Vérifie les deca de tous les semestres:
for formsemestre in FormSemestre.query:
@@ -69,7 +69,7 @@ def test_but_jury_GMP_lm(test_client):
app.set_sco_dept(DEPT)
# Construit la base de test GB une seule fois
# puis lance les tests de jury
- doc = yaml_setup.setup_from_yaml("tests/unit/cursus_but_gmp_iutlm.yaml")
+ doc = yaml_setup.setup_from_yaml("tests/ressources/yaml/cursus_but_gmp_iutlm.yaml")
formsemestres = FormSemestre.query.order_by(
FormSemestre.date_debut, FormSemestre.semestre_id
@@ -95,7 +95,7 @@ def test_but_jury_GEII_lyon(test_client):
app.set_sco_dept(DEPT)
# Construit la base de test GB une seule fois
# puis lance les tests de jury
- doc = yaml_setup.setup_from_yaml("tests/unit/cursus_but_geii_lyon.yaml")
+ doc = yaml_setup.setup_from_yaml("tests/ressources/yaml/cursus_but_geii_lyon.yaml")
formsemestres = FormSemestre.query.order_by(
FormSemestre.date_debut, FormSemestre.semestre_id
).all()
diff --git a/tests/unit/test_formsemestre.py b/tests/unit/test_formsemestre.py
index 3cb516afe6..ee25669531 100644
--- a/tests/unit/test_formsemestre.py
+++ b/tests/unit/test_formsemestre.py
@@ -3,12 +3,37 @@
""" Test création/accès/clonage formsemestre
"""
+from flask import Response
import pytest
-from tests.unit import yaml_setup
+from tests.unit import yaml_setup, call_view
import app
-from app.models import Formation
-from app.scodoc import sco_formsemestre_edit
+from app import db
+from app.models import Formation, FormSemestre
+from app.scodoc import (
+ sco_archives,
+ sco_cost_formation,
+ sco_debouche,
+ sco_edit_ue,
+ sco_evaluations,
+ sco_evaluation_check_abs,
+ sco_evaluation_recap,
+ sco_formsemestre_edit,
+ sco_formsemestre_inscriptions,
+ sco_formsemestre_status,
+ sco_groups,
+ sco_inscr_passage,
+ sco_lycee,
+ sco_moduleimpl_inscriptions,
+ sco_poursuite_dut,
+ sco_preferences,
+ sco_recapcomplet,
+ sco_report,
+ sco_undo_notes,
+)
+
+from app.scodoc import sco_utils as scu
+from app.views import notes, scolar
from config import TestConfig
DEPT = TestConfig.DEPT_TEST
@@ -34,3 +59,128 @@ def test_formsemestres_associate_new_version(test_client):
assert new_formation
assert formsemestres[0].formation_id == new_formation.id
assert formsemestres[1].formation_id == new_formation.id
+
+
+def test_formsemestre_misc_views(test_client):
+ """Test de nombreuses vues: test juste que la page ne plante,
+ pas de vérif du contenu ni de soumission si c'est un formulaire.
+
+ Note: les anciennes vues renvoient souvent des str au lieu de Response.
+ """
+ app.set_sco_dept(DEPT)
+ yaml_setup.setup_from_yaml("tests/ressources/yaml/simple_formsemestres.yaml")
+ formsemestre: FormSemestre = FormSemestre.query.first()
+
+ # ----- MENU SEMESTRE
+ _ = sco_formsemestre_status.formsemestre_status(formsemestre_id=formsemestre.id)
+ _ = sco_edit_ue.ue_table(formsemestre.formation_id)
+ _ = sco_formsemestre_edit.formsemestre_editwithmodules(formsemestre.id)
+ _ = sco_preferences.SemPreferences(formsemestre_id=formsemestre.id).edit()
+ _ = sco_formsemestre_edit.formsemestre_edit_options(formsemestre.id)
+ assert formsemestre.etat
+ formsemestre.flip_lock()
+ assert not formsemestre.etat
+ formsemestre.flip_lock()
+ assert formsemestre.etat
+ ans = sco_formsemestre_status.formsemestre_description(
+ formsemestre.id, with_evals=True
+ )
+ assert isinstance(ans, (str, Response)) # ici c'est une str
+ ans = sco_formsemestre_status.formsemestre_description(
+ formsemestre.id, with_evals=True, format="xls"
+ )
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.XLSX_MIMETYPE
+ ans = sco_formsemestre_status.formsemestre_description(
+ formsemestre.id, with_evals=True, format="pdf"
+ )
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.PDF_MIMETYPE
+ ans = sco_evaluation_check_abs.formsemestre_check_absences_html(formsemestre.id)
+ assert isinstance(ans, (str, Response))
+ # Appel direct de la vue: enlève les décorateurs:
+ ans = call_view(notes.formsemestre_enseignants_list, formsemestre.id)
+ assert isinstance(ans, (str, Response)) # ici str
+ # Juste la page dialogue avant opération::
+ ans = sco_formsemestre_edit.formsemestre_clone(formsemestre.id)
+ ans = sco_formsemestre_edit.formsemestre_associate_new_version(formsemestre.id)
+ ans = sco_formsemestre_edit.formsemestre_delete(formsemestre.id)
+
+ # ----- MENU INSCRIPTIONS
+ ans = sco_moduleimpl_inscriptions.moduleimpl_inscriptions_stats(formsemestre.id)
+ ans = sco_inscr_passage.formsemestre_inscr_passage(formsemestre.id)
+ ans = call_view(scolar.form_students_import_excel, formsemestre.id)
+ assert isinstance(ans, str)
+ ans = call_view(scolar.form_students_import_infos_admissions, formsemestre.id)
+ ans = sco_formsemestre_inscriptions.formsemestre_inscrits_ailleurs(formsemestre.id)
+
+ # ----- MENU GROUPES
+ ans = call_view(scolar.groups_view, formsemestre.id)
+ ans = call_view(scolar.partition_editor, formsemestre.id)
+ ans = sco_groups.edit_partition_form(formsemestre.id)
+
+ # ----- MENU NOTES
+ ans = sco_recapcomplet.formsemestre_recapcomplet(formsemestre.id)
+ ans = sco_recapcomplet.formsemestre_recapcomplet(formsemestre.id, tabformat="evals")
+ ans = sco_recapcomplet.formsemestre_recapcomplet(formsemestre.id, tabformat="xlsx")
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.XLSX_MIMETYPE
+ ans = sco_recapcomplet.formsemestre_recapcomplet(formsemestre.id, tabformat="json")
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.JSON_MIMETYPE
+ ans = sco_evaluation_recap.evaluations_recap(formsemestre.id)
+
+ # Bulletins pdf:
+ ans = call_view(notes.formsemestre_bulletins_pdf_choice, formsemestre.id)
+ assert isinstance(ans, str) # sans version, on a le formulaire de choix, une str
+ ans = call_view(
+ notes.formsemestre_bulletins_pdf_choice, formsemestre.id, version="long"
+ )
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.PDF_MIMETYPE
+ # on ne teste pas les mails :)
+ ans = sco_evaluations.formsemestre_evaluations_cal(formsemestre.id)
+ assert isinstance(ans, str)
+ sco_undo_notes.formsemestre_list_saisies_notes(formsemestre.id)
+
+ # ----- MENU JURY
+ ans = sco_recapcomplet.formsemestre_recapcomplet(formsemestre.id, mode_jury=True)
+ ans = sco_recapcomplet.formsemestre_recapcomplet(
+ formsemestre.id, mode_jury=True, tabformat="xlsx"
+ )
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.XLSX_MIMETYPE
+ ans = sco_recapcomplet.formsemestre_recapcomplet(
+ formsemestre.id, mode_jury=True, tabformat="json"
+ )
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.JSON_MIMETYPE
+ ans = sco_archives.formsemestre_archive(formsemestre.id)
+ ans = sco_archives.formsemestre_list_archives(formsemestre.id)
+
+ # ----- MENU STATISTIQUES
+ ans = sco_report.formsemestre_report_counts(formsemestre.id)
+ ans = sco_report.formsemestre_report_counts(formsemestre.id, format="xls")
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.XLSX_MIMETYPE
+ ans = sco_report.formsemestre_suivi_cohorte(formsemestre.id)
+ ans = sco_report.formsemestre_suivi_cohorte(formsemestre.id, format="pdf")
+ assert isinstance(ans, Response)
+ assert ans.status == "200 OK"
+ assert ans.mimetype == scu.PDF_MIMETYPE
+ ans = sco_report.formsemestre_graph_cursus(formsemestre.id)
+ ans = sco_report.formsemestre_suivi_cursus(formsemestre.id)
+ ans = sco_lycee.formsemestre_etuds_lycees(formsemestre.id)
+ ans = sco_poursuite_dut.formsemestre_poursuite_report(formsemestre.id)
+ # pas de test des avis de poursuite
+ ans = sco_debouche.report_debouche_date(start_year=2000)
+ ans = sco_cost_formation.formsemestre_estim_cost(formsemestre.id)
+ # pas de test des indicateurs de suivi BUT