diff --git a/app/models/formations.py b/app/models/formations.py index 15dae9d5c..e2eadf460 100644 --- a/app/models/formations.py +++ b/app/models/formations.py @@ -71,6 +71,8 @@ class Formation(db.Model): e.pop("_sa_instance_state", None) if "referentiel_competence" in e: e.pop("referentiel_competence") + e["code_specialite"] = e["code_specialite"] or "" + e["commentaire"] = e["commentaire"] or "" e["departement"] = self.departement.to_dict() e["formation_id"] = self.id # ScoDoc7 backward compat if with_refcomp_attrs and self.referentiel_competence: @@ -289,6 +291,6 @@ class Matiere(db.Model): e = dict(self.__dict__) e.pop("_sa_instance_state", None) # ScoDoc7 output_formators - e["ue_id"] = self.id e["numero"] = e["numero"] if e["numero"] else 0 + e["ue_id"] = self.id return e diff --git a/app/pe/pe_jurype.py b/app/pe/pe_jurype.py index 5c85c253c..f55623d37 100644 --- a/app/pe/pe_jurype.py +++ b/app/pe/pe_jurype.py @@ -48,7 +48,7 @@ from zipfile import ZipFile from app.comp import res_sem from app.comp.res_compat import NotesTableCompat -from app.models import FormSemestre +from app.models import Formation, FormSemestre from app.scodoc.gen_tables import GenTable, SeqGenTable import app.scodoc.sco_utils as scu @@ -65,10 +65,8 @@ def comp_nom_semestre_dans_parcours(sem): """Le nom a afficher pour titrer un semestre par exemple: "semestre 2 FI 2015" """ - from app.scodoc import sco_formations - - F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0] - parcours = codes_cursus.get_cursus_from_code(F["type_parcours"]) + formation: Formation = Formation.query.get_or_404(sem["formation_id"]) + parcours = codes_cursus.get_cursus_from_code(formation.type_parcours) return "%s %s %s %s" % ( parcours.SESSION_NAME, # eg "semestre" sem["semestre_id"], # eg 2 diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py index 67ba9851f..cef2c73ec 100644 --- a/app/scodoc/sco_bulletins.py +++ b/app/scodoc/sco_bulletins.py @@ -42,7 +42,7 @@ from app.scodoc.sco_utils import json_error from app.but import bulletin_but from app.comp import res_sem from app.comp.res_compat import NotesTableCompat -from app.models import FormSemestre, Identite, ModuleImplInscription +from app.models import Formation, FormSemestre, Identite, ModuleImplInscription from app.scodoc.sco_permissions import Permission from app.scodoc.sco_exceptions import AccessDenied, ScoValueError from app.scodoc import html_sco_header @@ -152,14 +152,9 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"): I["server_name"] = request.url_root # Formation et parcours - formation_dict = None if I["sem"]["formation_id"]: - formation_dicts = sco_formations.formation_list( - args={"formation_id": I["sem"]["formation_id"]} - ) - if formation_dicts: - formation_dict = formation_dicts[0] - if formation_dict is None: # what's the fuck ? + formation_dict = Formation.query.get_or_404(I["sem"]["formation_id"]).to_dict() + else: # what's the fuck ? formation_dict = { "acronyme": "?", "code_specialite": "", diff --git a/app/scodoc/sco_cursus_dut.py b/app/scodoc/sco_cursus_dut.py index 5b5b3c65a..babaede7d 100644 --- a/app/scodoc/sco_cursus_dut.py +++ b/app/scodoc/sco_cursus_dut.py @@ -336,9 +336,7 @@ class SituationEtudCursusClassic(SituationEtudCursus): if nb_ue > nb_max_ue: nb_max_ue = nb_ue # add formation_code to each sem: - sem["formation_code"] = sco_formations.formation_list( - args={"formation_id": sem["formation_id"]} - )[0]["formation_code"] + sem["formation_code"] = formsemestre.formation.formation_code # si sem peut servir à compenser le semestre courant, positionne # can_compensate sem["can_compensate"] = self.check_compensation_dut(sem, nt) diff --git a/app/scodoc/sco_edit_formation.py b/app/scodoc/sco_edit_formation.py index 2d2e348ab..14be5a28e 100644 --- a/app/scodoc/sco_edit_formation.py +++ b/app/scodoc/sco_edit_formation.py @@ -54,14 +54,11 @@ from app.scodoc import sco_formsemestre def formation_delete(formation_id=None, dialog_confirmed=False): """Delete a formation""" - F = sco_formations.formation_list(args={"formation_id": formation_id}) - if not F: - raise ScoValueError("formation inexistante !") - F = F[0] + formation: Formation = Formation.query.get_or_404(formation_id) H = [ html_sco_header.sco_header(page_title="Suppression d'une formation"), - """
Attention: la suppression d'une formation est irréversible et implique la supression de toutes les UE, matières et modules de la formation ! -
- """ - % F, + f"""Attention: la suppression d'une formation est irréversible + et implique la supression de toutes les UE, matières et modules de la formation ! +
+ """, OK="Supprimer cette formation", cancel_url=scu.NotesURL(), parameters={"formation_id": formation_id}, ) else: - do_formation_delete(F["formation_id"]) + do_formation_delete(formation_id) H.append( - """OK, formation supprimée.
- """ - % scu.NotesURL() + f"""OK, formation supprimée.
+ """ ) H.append(html_sco_header.sco_footer()) @@ -271,7 +269,7 @@ def formation_edit(formation_id=None, create=False): + tf_error_message( f"""Valeurs incorrectes: il existe déjà une formation avec même titre, + }">une formation avec même titre, acronyme et version. """ ) @@ -297,10 +295,10 @@ def do_formation_create(args): a = args.copy() if "formation_id" in a: del a["formation_id"] - F = sco_formations.formation_list(args=a) - if len(F) > 0: - log("do_formation_create: error: %d formations matching args=%s" % (len(F), a)) - raise ScoValueError("Formation non unique (%s) !" % str(a)) + f_dicts = sco_formations.formation_list(args=a) + if len(f_dicts) > 0: + log(f"do_formation_create: error: {len(f_dicts)} formations matching args={a}") + raise ScoValueError(f"Formation non unique ({a}) !") # Si pas de formation_code, l'enleve (default SQL) if "formation_code" in args and not args["formation_code"]: del args["formation_code"] diff --git a/app/scodoc/sco_edit_matiere.py b/app/scodoc/sco_edit_matiere.py index f0f2ce5b1..312f01ec1 100644 --- a/app/scodoc/sco_edit_matiere.py +++ b/app/scodoc/sco_edit_matiere.py @@ -253,7 +253,6 @@ def matiere_delete(matiere_id=None): def matiere_edit(matiere_id=None): """Edit matiere""" - from app.scodoc import sco_formations from app.scodoc import sco_edit_ue F = matiere_list(args={"matiere_id": matiere_id}) @@ -264,15 +263,14 @@ def matiere_edit(matiere_id=None): if not ues: raise ScoValueError("UE inexistante !") ue = ues[0] - Fo = sco_formations.formation_list(args={"formation_id": ue["formation_id"]})[0] - + formation: Formation = Formation.query.get_or_404(ue["formation_id"]) ues = sco_edit_ue.ue_list(args={"formation_id": ue["formation_id"]}) ue_names = ["%(acronyme)s (%(titre)s)" % u for u in ues] ue_ids = [u["ue_id"] for u in ues] H = [ html_sco_header.sco_header(page_title="Modification d'une matière"), """Les matières sont des groupes de modules dans une UE d'une formation donnée. Les matières servent surtout pour la diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py index 4bbd49117..5014435d4 100644 --- a/app/scodoc/sco_edit_module.py +++ b/app/scodoc/sco_edit_module.py @@ -900,21 +900,27 @@ def module_table(formation_id): if not formation_id: raise ScoValueError("invalid formation !") - F = sco_formations.formation_list(args={"formation_id": formation_id})[0] + formation: Formation = Formation.query.get_or_404(formation_id) H = [ - html_sco_header.sco_header(page_title="Liste des modules de %(titre)s" % F), - """
Utiliser cette page pour enregistrer une UE validée antérieurement, + f"""
Utiliser cette page pour enregistrer une UE validée antérieurement, dans un semestre hors ScoDoc.
Les UE validées dans ScoDoc sont déjà - automatiquement prises en compte. Cette page n'est utile que pour les étudiants ayant - suivi un début de cursus dans un autre établissement, ou bien dans un semestre géré sans - ScoDoc et qui redouble ce semestre (ne pas utiliser pour les semestres précédents !). + automatiquement prises en compte. Cette page n'est utile que pour les étudiants ayant + suivi un début de cursus dans un autre établissement, ou bien dans un semestre géré sans + ScoDoc et qui redouble ce semestre + (ne pas utiliser pour les semestres précédents !).
-Notez que l'UE est validée, avec enregistrement immédiat de la décision et - l'attribution des ECTS.
""", - "On ne peut prendre en compte ici que les UE du cursus %(titre)s
" - % Fo, +Notez que l'UE est validée, avec enregistrement immédiat de la décision et + l'attribution des ECTS.
+On ne peut prendre en compte ici que les UE du cursus {formation.titre}
+ """, ] # Toutes les UE de cette formation sont présentées (même celles des autres semestres) - ues = sco_edit_ue.ue_list({"formation_id": Fo["formation_id"]}) - ue_names = ["Choisir..."] + ["%(acronyme)s %(titre)s" % ue for ue in ues] - ue_ids = [""] + [ue["ue_id"] for ue in ues] + ues = formation.ues.order_by(UniteEns.numero) + ue_names = ["Choisir..."] + [f"{ue.acronyme} {ue.titre}" for ue in ues] + ue_ids = [""] + [ue.id for ue in ues] tf = TrivialFormulator( request.base_url, scu.get_request_args(), @@ -1155,7 +1155,7 @@ def formsemestre_validate_previous_ue(formsemestre_id, etudid): """ - warn, ue_multiples = check_formation_ues(Fo["formation_id"]) + warn, ue_multiples = check_formation_ues(formation.id) return "\n".join(H) + tf[1] + X + warn + html_sco_header.sco_footer() elif tf[0] == -1: return flask.redirect( @@ -1176,10 +1176,14 @@ def formsemestre_validate_previous_ue(formsemestre_id, etudid): tf[2]["date"], semestre_id=semestre_id, ) + flash("Validation d'UE enregistrée") return flask.redirect( - scu.ScoURL() - + "/Notes/formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s&head_message=Validation%%20d'UE%%20enregistree" - % (formsemestre_id, etudid) + url_for( + "notes.formsemestre_bulletinetud", + scodoc_dept=g.scodoc_dept, + formsemestre_id=formsemestre_id, + etudid=etudid, + ) ) diff --git a/app/scodoc/sco_pvjury.py b/app/scodoc/sco_pvjury.py index a1c28cb21..c8924119c 100644 --- a/app/scodoc/sco_pvjury.py +++ b/app/scodoc/sco_pvjury.py @@ -58,6 +58,7 @@ from flask import g, request from app.comp import res_sem from app.comp.res_compat import NotesTableCompat from app.models import ( + Formation, FormSemestre, UniteEns, ScolarAutorisationInscription, @@ -74,7 +75,6 @@ from app.scodoc import sco_cursus from app.scodoc import sco_cursus_dut from app.scodoc import sco_edit_ue from app.scodoc import sco_etud -from app.scodoc import sco_formations from app.scodoc import sco_formsemestre from app.scodoc import sco_groups from app.scodoc import sco_groups_view @@ -368,9 +368,7 @@ def dict_pvjury( "is_apc": nt.is_apc, "has_prev": has_prev, "semestre_non_terminal": semestre_non_terminal, - "formation": sco_formations.formation_list( - args={"formation_id": sem["formation_id"]} - )[0], + "formation": Formation.query.get_or_404(sem["formation_id"]).to_dict(), "decisions": decisions, "decisions_dict": D, } @@ -734,7 +732,7 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids=[], etudid=None): def descrform_pvjury(sem): """Définition de formulaire pour PV jury PDF""" - F = sco_formations.formation_list(formation_id=sem["formation_id"])[0] + f_dict = Formation.query.get_or_404(sem["formation_id"]).to_dict() return [ ( "date_commission", @@ -779,7 +777,7 @@ def descrform_pvjury(sem): "size": 64, "title": "Titre du PV", "explanation": "par défaut, titre officiel de la formation", - "default": F["titre_officiel"], + "default": f_dict["titre_officiel"], }, ), ( diff --git a/app/views/notes.py b/app/views/notes.py index 94dc2b2f6..c3e487b26 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -674,32 +674,6 @@ def index_html(): # --- Formations -sco_publish( - "/do_formation_create", - sco_edit_formation.do_formation_create, - Permission.ScoChangeFormation, - methods=["GET", "POST"], -) - -sco_publish( - "/do_formation_delete", - sco_edit_formation.do_formation_delete, - Permission.ScoChangeFormation, - methods=["GET", "POST"], -) - - -@bp.route("/formation_list") -@scodoc -@permission_required(Permission.ScoView) -@scodoc7func -def formation_list(format=None, formation_id=None, args={}): - """List formation(s) with given id, or matching args - (when args is given, formation_id is ignored). - """ - r = sco_formations.formation_list(formation_id=formation_id, args=args) - return scu.sendResult(r, name="formation", format=format) - @bp.route("/formation_export") @scodoc diff --git a/tests/unit/test_formations.py b/tests/unit/test_formations.py index 38a40378d..b3aaba0bc 100644 --- a/tests/unit/test_formations.py +++ b/tests/unit/test_formations.py @@ -49,7 +49,7 @@ import os import flask import pytest -from app.models.moduleimpls import ModuleImpl +from app.models import Formation, ModuleImpl from app.scodoc import sco_edit_formation, sco_formsemestre from app.scodoc import sco_edit_matiere from app.scodoc import sco_edit_module @@ -155,25 +155,21 @@ def test_formations(test_client): formsemestre_id=formsemestre_idt, ) - # --- Afficher la liste des formations + # --- Récupérer la liste des formations - lif = notes.formation_list(format="json", formation_id=formation_id) - # lif est une Response car on a appelé une vue (1er appel) - assert isinstance(lif, flask.Response) - load_lif = json.loads(lif.get_data().decode("utf-8")) - assert len(load_lif) == 1 - assert load_lif[0]["acronyme"] == f["acronyme"] - assert load_lif[0]["titre_officiel"] == f["titre_officiel"] - assert load_lif[0]["formation_id"] == formation_id - assert load_lif[0]["titre"] == f["titre"] + formation = Formation.query.get(formation_id) + assert isinstance(formation, Formation) + assert formation.acronyme == f["acronyme"] + assert formation.titre_officiel == f["titre_officiel"] + assert formation.id == formation_id + assert formation.titre == f["titre"] - lif2 = notes.formation_list(format="json").get_data(as_text=True) - # lif2 est un chaine - assert isinstance(lif2, str) - load_lif2 = json.loads(lif2) - assert len(load_lif2) == 2 - assert load_lif2[0] == load_lif[0] - assert load_lif2[1]["titre"] == formation2["titre"] + f_dict = formation.to_dict() + assert isinstance(f_dict, dict) + del f_dict["departement"] + # pour le test: + f_dict["referentiel_competence_id"] = f_dict["referentiel_competence_id"] or "" + assert f_dict == f # --- Export de formation_id @@ -324,10 +320,8 @@ def test_formations(test_client): # --- Suppression d'une formation sco_edit_formation.do_formation_delete(formation_id=formation_id2) - lif3 = notes.formation_list(format="json").get_data(as_text=True) - assert isinstance(lif3, str) - load_lif3 = json.loads(lif3) - assert len(load_lif3) == 1 + formation = Formation.query.get(formation_id2) + assert formation is None def test_import_formation(test_client, filename="formation-exemple-1.xml"):