Modernisation d'une partie des accès aux formations

This commit is contained in:
Emmanuel Viennet 2023-02-18 00:13:00 +01:00
parent 597be47afb
commit 72457a0651
18 changed files with 119 additions and 165 deletions

View File

@ -71,6 +71,8 @@ class Formation(db.Model):
e.pop("_sa_instance_state", None) e.pop("_sa_instance_state", None)
if "referentiel_competence" in e: if "referentiel_competence" in e:
e.pop("referentiel_competence") e.pop("referentiel_competence")
e["code_specialite"] = e["code_specialite"] or ""
e["commentaire"] = e["commentaire"] or ""
e["departement"] = self.departement.to_dict() e["departement"] = self.departement.to_dict()
e["formation_id"] = self.id # ScoDoc7 backward compat e["formation_id"] = self.id # ScoDoc7 backward compat
if with_refcomp_attrs and self.referentiel_competence: if with_refcomp_attrs and self.referentiel_competence:
@ -289,6 +291,6 @@ class Matiere(db.Model):
e = dict(self.__dict__) e = dict(self.__dict__)
e.pop("_sa_instance_state", None) e.pop("_sa_instance_state", None)
# ScoDoc7 output_formators # ScoDoc7 output_formators
e["ue_id"] = self.id
e["numero"] = e["numero"] if e["numero"] else 0 e["numero"] = e["numero"] if e["numero"] else 0
e["ue_id"] = self.id
return e return e

View File

@ -48,7 +48,7 @@ from zipfile import ZipFile
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat 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 from app.scodoc.gen_tables import GenTable, SeqGenTable
import app.scodoc.sco_utils as scu 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 """Le nom a afficher pour titrer un semestre
par exemple: "semestre 2 FI 2015" par exemple: "semestre 2 FI 2015"
""" """
from app.scodoc import sco_formations formation: Formation = Formation.query.get_or_404(sem["formation_id"])
parcours = codes_cursus.get_cursus_from_code(formation.type_parcours)
F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0]
parcours = codes_cursus.get_cursus_from_code(F["type_parcours"])
return "%s %s %s %s" % ( return "%s %s %s %s" % (
parcours.SESSION_NAME, # eg "semestre" parcours.SESSION_NAME, # eg "semestre"
sem["semestre_id"], # eg 2 sem["semestre_id"], # eg 2

View File

@ -42,7 +42,7 @@ from app.scodoc.sco_utils import json_error
from app.but import bulletin_but from app.but import bulletin_but
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat 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_permissions import Permission
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
from app.scodoc import html_sco_header 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 I["server_name"] = request.url_root
# Formation et parcours # Formation et parcours
formation_dict = None
if I["sem"]["formation_id"]: if I["sem"]["formation_id"]:
formation_dicts = sco_formations.formation_list( formation_dict = Formation.query.get_or_404(I["sem"]["formation_id"]).to_dict()
args={"formation_id": I["sem"]["formation_id"]} else: # what's the fuck ?
)
if formation_dicts:
formation_dict = formation_dicts[0]
if formation_dict is None: # what's the fuck ?
formation_dict = { formation_dict = {
"acronyme": "?", "acronyme": "?",
"code_specialite": "", "code_specialite": "",

View File

@ -336,9 +336,7 @@ class SituationEtudCursusClassic(SituationEtudCursus):
if nb_ue > nb_max_ue: if nb_ue > nb_max_ue:
nb_max_ue = nb_ue nb_max_ue = nb_ue
# add formation_code to each sem: # add formation_code to each sem:
sem["formation_code"] = sco_formations.formation_list( sem["formation_code"] = formsemestre.formation.formation_code
args={"formation_id": sem["formation_id"]}
)[0]["formation_code"]
# si sem peut servir à compenser le semestre courant, positionne # si sem peut servir à compenser le semestre courant, positionne
# can_compensate # can_compensate
sem["can_compensate"] = self.check_compensation_dut(sem, nt) sem["can_compensate"] = self.check_compensation_dut(sem, nt)

View File

@ -54,14 +54,11 @@ from app.scodoc import sco_formsemestre
def formation_delete(formation_id=None, dialog_confirmed=False): def formation_delete(formation_id=None, dialog_confirmed=False):
"""Delete a formation""" """Delete a formation"""
F = sco_formations.formation_list(args={"formation_id": formation_id}) formation: Formation = Formation.query.get_or_404(formation_id)
if not F:
raise ScoValueError("formation inexistante !")
F = F[0]
H = [ H = [
html_sco_header.sco_header(page_title="Suppression d'une formation"), html_sco_header.sco_header(page_title="Suppression d'une formation"),
"""<h2>Suppression de la formation %(titre)s (%(acronyme)s)</h2>""" % F, f"""<h2>Suppression de la formation {formation.titre} ({formation.acronyme})</h2>""",
] ]
sems = sco_formsemestre.do_formsemestre_list({"formation_id": formation_id}) sems = sco_formsemestre.do_formsemestre_list({"formation_id": formation_id})
@ -80,21 +77,22 @@ def formation_delete(formation_id=None, dialog_confirmed=False):
else: else:
if not dialog_confirmed: if not dialog_confirmed:
return scu.confirm_dialog( return scu.confirm_dialog(
"""<h2>Confirmer la suppression de la formation %(titre)s (%(acronyme)s) ?</h2> f"""<h2>Confirmer la suppression de la formation
<p><b>Attention:</b> la suppression d'une formation est <b>irréversible</b> et implique la supression de toutes les UE, matières et modules de la formation ! {formation.titre} ({formation.acronyme}) ?
</p> </h2>
""" <p><b>Attention:</b> la suppression d'une formation est <b>irréversible</b>
% F, et implique la supression de toutes les UE, matières et modules de la formation !
</p>
""",
OK="Supprimer cette formation", OK="Supprimer cette formation",
cancel_url=scu.NotesURL(), cancel_url=scu.NotesURL(),
parameters={"formation_id": formation_id}, parameters={"formation_id": formation_id},
) )
else: else:
do_formation_delete(F["formation_id"]) do_formation_delete(formation_id)
H.append( H.append(
"""<p>OK, formation supprimée.</p> f"""<p>OK, formation supprimée.</p>
<p><a class="stdlink" href="%s">continuer</a></p>""" <p><a class="stdlink" href="{scu.NotesURL()}">continuer</a></p>"""
% scu.NotesURL()
) )
H.append(html_sco_header.sco_footer()) H.append(html_sco_header.sco_footer())
@ -271,7 +269,7 @@ def formation_edit(formation_id=None, create=False):
+ tf_error_message( + tf_error_message(
f"""Valeurs incorrectes: il existe déjà <a href="{ f"""Valeurs incorrectes: il existe déjà <a href="{
url_for('notes.ue_table', scodoc_dept=g.scodoc_dept, formation_id=others[0]["id"]) url_for('notes.ue_table', scodoc_dept=g.scodoc_dept, formation_id=others[0]["id"])
}">une formation</a> avec même titre, }">une formation</a> avec même titre,
acronyme et version. acronyme et version.
""" """
) )
@ -297,10 +295,10 @@ def do_formation_create(args):
a = args.copy() a = args.copy()
if "formation_id" in a: if "formation_id" in a:
del a["formation_id"] del a["formation_id"]
F = sco_formations.formation_list(args=a) f_dicts = sco_formations.formation_list(args=a)
if len(F) > 0: if len(f_dicts) > 0:
log("do_formation_create: error: %d formations matching args=%s" % (len(F), a)) log(f"do_formation_create: error: {len(f_dicts)} formations matching args={a}")
raise ScoValueError("Formation non unique (%s) !" % str(a)) raise ScoValueError(f"Formation non unique ({a}) !")
# Si pas de formation_code, l'enleve (default SQL) # Si pas de formation_code, l'enleve (default SQL)
if "formation_code" in args and not args["formation_code"]: if "formation_code" in args and not args["formation_code"]:
del args["formation_code"] del args["formation_code"]

View File

@ -253,7 +253,6 @@ def matiere_delete(matiere_id=None):
def matiere_edit(matiere_id=None): def matiere_edit(matiere_id=None):
"""Edit matiere""" """Edit matiere"""
from app.scodoc import sco_formations
from app.scodoc import sco_edit_ue from app.scodoc import sco_edit_ue
F = matiere_list(args={"matiere_id": matiere_id}) F = matiere_list(args={"matiere_id": matiere_id})
@ -264,15 +263,14 @@ def matiere_edit(matiere_id=None):
if not ues: if not ues:
raise ScoValueError("UE inexistante !") raise ScoValueError("UE inexistante !")
ue = ues[0] 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"]}) ues = sco_edit_ue.ue_list(args={"formation_id": ue["formation_id"]})
ue_names = ["%(acronyme)s (%(titre)s)" % u for u in ues] ue_names = ["%(acronyme)s (%(titre)s)" % u for u in ues]
ue_ids = [u["ue_id"] for u in ues] ue_ids = [u["ue_id"] for u in ues]
H = [ H = [
html_sco_header.sco_header(page_title="Modification d'une matière"), html_sco_header.sco_header(page_title="Modification d'une matière"),
"""<h2>Modification de la matière %(titre)s""" % F, """<h2>Modification de la matière %(titre)s""" % F,
"""(formation %(acronyme)s, version %(version)s)</h2>""" % Fo, f"""(formation ({formation.acronyme}, version {formation.version})</h2>""",
] ]
help = """<p class="help">Les matières sont des groupes de modules dans une UE help = """<p class="help">Les matières sont des groupes de modules dans une UE
d'une formation donnée. Les matières servent surtout pour la d'une formation donnée. Les matières servent surtout pour la

View File

@ -900,21 +900,27 @@ def module_table(formation_id):
if not formation_id: if not formation_id:
raise ScoValueError("invalid formation !") 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 = [ H = [
html_sco_header.sco_header(page_title="Liste des modules de %(titre)s" % F), html_sco_header.sco_header(
"""<h2>Listes des modules dans la formation %(titre)s (%(acronyme)s)</h2>""" page_title=f"Liste des modules de {formation.titre}"
% F, ),
'<ul class="notes_module_list">', f"""<h2>Listes des modules dans la formation {formation.titre} ({formation.acronyme}</h2>
<ul class="notes_module_list">
""",
] ]
editable = current_user.has_permission(Permission.ScoChangeFormation) editable = current_user.has_permission(Permission.ScoChangeFormation)
for Mod in module_list(args={"formation_id": formation_id}): for module_dict in module_list(args={"formation_id": formation_id}):
H.append('<li class="notes_module_list">%s' % Mod) H.append('<li class="notes_module_list">%s' % module_dict)
if editable: if editable:
H.append('<a href="module_edit?module_id=%(module_id)s">modifier</a>' % Mod)
H.append( H.append(
'<a href="module_delete?module_id=%(module_id)s">supprimer</a>' % Mod '<a href="module_edit?module_id=%(module_id)s">modifier</a>'
% module_dict
)
H.append(
'<a href="module_delete?module_id=%(module_id)s">supprimer</a>'
% module_dict
) )
H.append("</li>") H.append("</li>")
H.append("</ul>") H.append("</ul>")

View File

@ -36,10 +36,10 @@ from flask import url_for, g, send_file, request
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.models import Formation
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
from app.scodoc import sco_apogee_csv from app.scodoc import sco_apogee_csv
from app.scodoc import sco_etape_apogee from app.scodoc import sco_etape_apogee
from app.scodoc import sco_formations
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
from app.scodoc import sco_portal_apogee from app.scodoc import sco_portal_apogee
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
@ -341,21 +341,24 @@ def apo_semset_maq_status(
if missing: if missing:
formation_ids = {sem["formation_id"] for sem in semset.sems} formation_ids = {sem["formation_id"] for sem in semset.sems}
formations = [ formations = [
sco_formations.formation_list(formation_id=i)[0] for i in formation_ids Formation.query.get_or_404(formation_id) for formation_id in formation_ids
] ]
# log('formations=%s' % formations)
H.append( H.append(
'<div class="apo_csv_status_missing_elems"><span class="fontred">Elements Apogée absents dans ScoDoc: </span><span class="apo_elems fontred">%s</span>' f"""<div class="apo_csv_status_missing_elems">
% ", ".join(sorted(missing)) <span class="fontred">Elements Apogée absents dans ScoDoc: </span>
) <span class="apo_elems fontred">{
H.append( ", ".join(sorted(missing))
'<div class="help">Ces éléments de la maquette Apogée ne sont pas déclarés dans ScoDoc et ne seront donc pas remplis.</div><div> Vous pouvez les déclarer dans les programmes pédagogiques: ' }</span>
<div class="help">Ces éléments de la maquette Apogée ne sont pas déclarés dans
ScoDoc et ne seront donc pas remplis.</div><div> Vous pouvez les déclarer
dans les programmes pédagogiques: """
) )
H.append( H.append(
", ".join( ", ".join(
[ [
'<a class="stdlink" href="ue_table?formation_id=%(formation_id)s">%(acronyme)s v%(version)s</a>' f"""<a class="stdlink" href="{
% f url_for("notes.ue_table",scodoc_dept=g.scodoc_dept, formation_id=f.id)
}">{f.acronyme} v{f.version}</a>"""
for f in formations for f in formations
] ]
) )

View File

@ -35,10 +35,10 @@ from app.models import FormSemestre
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.models import Formation
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
from app.scodoc import sco_bac from app.scodoc import sco_bac
from app.scodoc import codes_cursus from app.scodoc import codes_cursus
from app.scodoc import sco_cache
from app.scodoc import sco_formations from app.scodoc import sco_formations
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc import sco_pvjury from app.scodoc import sco_pvjury
@ -65,9 +65,7 @@ def _build_results_table(start_date=None, end_date=None, types_parcours=[]):
semlist = [dpv["formsemestre"] for dpv in dpv_by_sem.values() if dpv] semlist = [dpv["formsemestre"] for dpv in dpv_by_sem.values() if dpv]
semlist_parcours = [] semlist_parcours = []
for sem in semlist: for sem in semlist:
sem["formation"] = sco_formations.formation_list( sem["formation"] = Formation.query.get_or_404(sem["formation_id"]).to_dict()
args={"formation_id": sem["formation_id"]}
)[0]
sem["parcours"] = codes_cursus.get_cursus_from_code( sem["parcours"] = codes_cursus.get_cursus_from_code(
sem["formation"]["type_parcours"] sem["formation"]["type_parcours"]
) )

View File

@ -82,7 +82,7 @@ _formationEditor = ndb.EditableTable(
) )
def formation_list(formation_id=None, args={}): def formation_list(formation_id=None, args={}): ### XXX obsolete, à supprimer
"""List formation(s) with given id, or matching args """List formation(s) with given id, or matching args
(when args is given, formation_id is ignored). (when args is given, formation_id is ignored).
""" """
@ -295,14 +295,10 @@ def formation_import_xml(doc: str, import_tags=True, use_local_refcomp=False):
referentiel_competence_id = _formation_retreive_refcomp(f_dict) referentiel_competence_id = _formation_retreive_refcomp(f_dict)
f_dict["referentiel_competence_id"] = referentiel_competence_id f_dict["referentiel_competence_id"] = referentiel_competence_id
# find new version number # find new version number
formations = sco_formations.formation_list( formations = Formation.query.filter_by(
args={ acronyme=f_dict["acronyme"], titre=f_dict["titre"], dept_id=f_dict["dept_id"]
"acronyme": f_dict["acronyme"],
"titre": f_dict["titre"],
"dept_id": f_dict["dept_id"],
}
) )
if formations: if formations.count():
version = max(f["version"] or 0 for f in formations) version = max(f["version"] or 0 for f in formations)
else: else:
version = 0 version = 0

View File

@ -38,7 +38,7 @@ import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.models import Departement from app.models import Departement
from app.models import FormSemestre from app.models import Formation, FormSemestre
from app.scodoc import sco_cache, codes_cursus, sco_formations, sco_preferences from app.scodoc import sco_cache, codes_cursus, sco_formations, sco_preferences
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
from app.scodoc.codes_cursus import NO_SEMESTRE_ID from app.scodoc.codes_cursus import NO_SEMESTRE_ID
@ -145,13 +145,8 @@ def _formsemestre_enrich(sem):
# imports ici pour eviter refs circulaires # imports ici pour eviter refs circulaires
from app.scodoc import sco_formsemestre_edit from app.scodoc import sco_formsemestre_edit
formations = sco_formations.formation_list( formation: Formation = Formation.query.get_or_404(sem["formation_id"])
args={"formation_id": sem["formation_id"]} parcours = codes_cursus.get_cursus_from_code(formation.type_parcours)
)
if not formations:
raise ScoValueError("pas de formation pour ce semestre !")
F = formations[0]
parcours = codes_cursus.get_cursus_from_code(F["type_parcours"])
# 'S1', 'S2', ... ou '' pour les monosemestres # 'S1', 'S2', ... ou '' pour les monosemestres
if sem["semestre_id"] != NO_SEMESTRE_ID: if sem["semestre_id"] != NO_SEMESTRE_ID:
sem["sem_id_txt"] = "S%s" % sem["semestre_id"] sem["sem_id_txt"] = "S%s" % sem["semestre_id"]
@ -216,7 +211,7 @@ def _formsemestre_enrich(sem):
sem["mois_fin"], sem["mois_fin"],
) )
sem["session_id"] = sco_formsemestre_edit.get_formsemestre_session_id( sem["session_id"] = sco_formsemestre_edit.get_formsemestre_session_id(
sem, F, parcours sem, formation.code_specialite, parcours
) )
sem["etapes"] = read_formsemestre_etapes(sem["formsemestre_id"]) sem["etapes"] = read_formsemestre_etapes(sem["formsemestre_id"])
sem["etapes_apo_str"] = formsemestre_etape_apo_str(sem) sem["etapes_apo_str"] = formsemestre_etape_apo_str(sem)

View File

@ -1866,7 +1866,7 @@ def formsemestre_edit_uecoefs(formsemestre_id, err_ue_id=None):
# ----- identification externe des sessions (pour SOJA et autres logiciels) # ----- identification externe des sessions (pour SOJA et autres logiciels)
def get_formsemestre_session_id(sem, F, parcours): def get_formsemestre_session_id(sem, code_specialite, parcours):
"""Identifiant de session pour ce semestre """Identifiant de session pour ce semestre
Obsolete: vooir FormSemestre.session_id() #sco7 Obsolete: vooir FormSemestre.session_id() #sco7
""" """
@ -1885,9 +1885,11 @@ def get_formsemestre_session_id(sem, F, parcours):
decale = scu.sem_decale_str(sem) decale = scu.sem_decale_str(sem)
semestre_id = "S%d" % sem["semestre_id"] + decale semestre_id = "S%d" % sem["semestre_id"] + decale
else: else:
semestre_id = F["code_specialite"] semestre_id = code_specialite
annee_sco = str(scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"])) annee_sco = str(scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"]))
return scu.sanitize_string( return scu.sanitize_string(
"-".join((imputation_dept, parcours_type, modalite, semestre_id, annee_sco)) "-".join(
(imputation_dept, parcours_type, modalite, semestre_id or "", annee_sco)
)
) )

View File

@ -40,6 +40,7 @@ from flask_login import current_user
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.models import ( from app.models import (
Formation,
FormSemestre, FormSemestre,
FormSemestreUECoef, FormSemestreUECoef,
Identite, Identite,
@ -54,7 +55,6 @@ from app.scodoc import sco_formations
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_formsemestre_validation from app.scodoc import sco_formsemestre_validation
from app.scodoc import sco_etud
from app.scodoc.codes_cursus import UE_SPORT from app.scodoc.codes_cursus import UE_SPORT
@ -63,11 +63,9 @@ def formsemestre_ext_create(etudid, sem_params):
sem_params: dict nécessaire à la création du formsemestre sem_params: dict nécessaire à la création du formsemestre
""" """
# Check args # Check args
_formation = sco_formations.formation_list( _ = Formation.query.get_or_404(sem_params["formation_id"])
args={"formation_id": sem_params["formation_id"]}
)[0]
if etudid: if etudid:
_etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] _ = Identite.query.get_or_404(etudid)
# Create formsemestre # Create formsemestre
sem_params["modalite"] = "EXT" sem_params["modalite"] = "EXT"

View File

@ -616,10 +616,7 @@ def formsemestre_description_table(
).first_or_404() ).first_or_404()
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre) nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
use_ue_coefs = sco_preferences.get_preference("use_ue_coefs", formsemestre_id) use_ue_coefs = sco_preferences.get_preference("use_ue_coefs", formsemestre_id)
F = sco_formations.formation_list(args={"formation_id": formsemestre.formation_id})[ parcours = codes_cursus.get_cursus_from_code(formsemestre.formation.type_parcours)
0
]
parcours = codes_cursus.get_cursus_from_code(F["type_parcours"])
# --- Colonnes à proposer: # --- Colonnes à proposer:
columns_ids = ["UE", "Code", "Module"] columns_ids = ["UE", "Code", "Module"]
if with_parcours: if with_parcours:

View File

@ -30,7 +30,7 @@
import time import time
import flask import flask
from flask import url_for, g, request from flask import url_for, flash, g, request
from app.models.etudiants import Identite from app.models.etudiants import Identite
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
@ -39,7 +39,7 @@ from app import db, log
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.models import FormSemestre, UniteEns from app.models import Formation, FormSemestre, UniteEns
from app.models.notes import etud_has_notes_attente from app.models.notes import etud_has_notes_attente
from app.models.validations import ( from app.models.validations import (
ScolarAutorisationInscription, ScolarAutorisationInscription,
@ -1066,8 +1066,7 @@ def formsemestre_validate_previous_ue(formsemestre_id, etudid):
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
sem = sco_formsemestre.get_formsemestre(formsemestre_id) sem = sco_formsemestre.get_formsemestre(formsemestre_id)
Fo = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0] formation: Formation = Formation.query.get_or_404(sem["formation_id"])
H = [ H = [
html_sco_header.sco_header( html_sco_header.sco_header(
page_title="Validation UE", page_title="Validation UE",
@ -1083,23 +1082,24 @@ def formsemestre_validate_previous_ue(formsemestre_id, etudid):
sco_photos.etud_photo_html(etud, title="fiche de %s" % etud["nom"]), sco_photos.etud_photo_html(etud, title="fiche de %s" % etud["nom"]),
) )
), ),
"""<p class="help">Utiliser cette page pour enregistrer une UE validée antérieurement, f"""<p class="help">Utiliser cette page pour enregistrer une UE validée antérieurement,
<em>dans un semestre hors ScoDoc</em>.</p> <em>dans un semestre hors ScoDoc</em>.</p>
<p><b>Les UE validées dans ScoDoc sont déjà <p><b>Les UE validées dans ScoDoc sont déjà
automatiquement prises en compte</b>. Cette page n'est utile que pour les étudiants ayant automatiquement prises en compte</b>. Cette page n'est utile que pour les étudiants ayant
suivi un début de cursus dans <b>un autre établissement</b>, ou bien dans un semestre géré <b>sans suivi un début de cursus dans <b>un autre établissement</b>, ou bien dans un semestre géré <b>sans
ScoDoc</b> et qui <b>redouble</b> ce semestre (<em>ne pas utiliser pour les semestres précédents !</em>). ScoDoc</b> et qui <b>redouble</b> ce semestre
(<em>ne pas utiliser pour les semestres précédents !</em>).
</p> </p>
<p>Notez que l'UE est validée, avec enregistrement immédiat de la décision et <p>Notez que l'UE est validée, avec enregistrement immédiat de la décision et
l'attribution des ECTS.</p>""", l'attribution des ECTS.</p>
"<p>On ne peut prendre en compte ici que les UE du cursus <b>%(titre)s</b></p>" <p>On ne peut prendre en compte ici que les UE du cursus <b>{formation.titre}</b></p>
% Fo, """,
] ]
# Toutes les UE de cette formation sont présentées (même celles des autres semestres) # 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"]}) ues = formation.ues.order_by(UniteEns.numero)
ue_names = ["Choisir..."] + ["%(acronyme)s %(titre)s" % ue for ue in ues] ue_names = ["Choisir..."] + [f"{ue.acronyme} {ue.titre}" for ue in ues]
ue_ids = [""] + [ue["ue_id"] for ue in ues] ue_ids = [""] + [ue.id for ue in ues]
tf = TrivialFormulator( tf = TrivialFormulator(
request.base_url, request.base_url,
scu.get_request_args(), scu.get_request_args(),
@ -1155,7 +1155,7 @@ def formsemestre_validate_previous_ue(formsemestre_id, etudid):
<div id="ue_list_etud_validations"><!-- filled by get_etud_ue_cap_html --></div> <div id="ue_list_etud_validations"><!-- filled by get_etud_ue_cap_html --></div>
<div id="ue_list_code"><!-- filled by ue_sharing_code --></div> <div id="ue_list_code"><!-- filled by ue_sharing_code --></div>
""" """
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() return "\n".join(H) + tf[1] + X + warn + html_sco_header.sco_footer()
elif tf[0] == -1: elif tf[0] == -1:
return flask.redirect( return flask.redirect(
@ -1176,10 +1176,14 @@ def formsemestre_validate_previous_ue(formsemestre_id, etudid):
tf[2]["date"], tf[2]["date"],
semestre_id=semestre_id, semestre_id=semestre_id,
) )
flash("Validation d'UE enregistrée")
return flask.redirect( return flask.redirect(
scu.ScoURL() url_for(
+ "/Notes/formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s&head_message=Validation%%20d'UE%%20enregistree" "notes.formsemestre_bulletinetud",
% (formsemestre_id, etudid) scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id,
etudid=etudid,
)
) )

View File

@ -58,6 +58,7 @@ from flask import g, request
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.models import ( from app.models import (
Formation,
FormSemestre, FormSemestre,
UniteEns, UniteEns,
ScolarAutorisationInscription, ScolarAutorisationInscription,
@ -74,7 +75,6 @@ from app.scodoc import sco_cursus
from app.scodoc import sco_cursus_dut from app.scodoc import sco_cursus_dut
from app.scodoc import sco_edit_ue from app.scodoc import sco_edit_ue
from app.scodoc import sco_etud from app.scodoc import sco_etud
from app.scodoc import sco_formations
from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre
from app.scodoc import sco_groups from app.scodoc import sco_groups
from app.scodoc import sco_groups_view from app.scodoc import sco_groups_view
@ -368,9 +368,7 @@ def dict_pvjury(
"is_apc": nt.is_apc, "is_apc": nt.is_apc,
"has_prev": has_prev, "has_prev": has_prev,
"semestre_non_terminal": semestre_non_terminal, "semestre_non_terminal": semestre_non_terminal,
"formation": sco_formations.formation_list( "formation": Formation.query.get_or_404(sem["formation_id"]).to_dict(),
args={"formation_id": sem["formation_id"]}
)[0],
"decisions": decisions, "decisions": decisions,
"decisions_dict": D, "decisions_dict": D,
} }
@ -734,7 +732,7 @@ def formsemestre_pvjury_pdf(formsemestre_id, group_ids=[], etudid=None):
def descrform_pvjury(sem): def descrform_pvjury(sem):
"""Définition de formulaire pour PV jury PDF""" """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 [ return [
( (
"date_commission", "date_commission",
@ -779,7 +777,7 @@ def descrform_pvjury(sem):
"size": 64, "size": 64,
"title": "Titre du PV", "title": "Titre du PV",
"explanation": "par défaut, titre officiel de la formation", "explanation": "par défaut, titre officiel de la formation",
"default": F["titre_officiel"], "default": f_dict["titre_officiel"],
}, },
), ),
( (

View File

@ -674,32 +674,6 @@ def index_html():
# --- Formations # --- 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") @bp.route("/formation_export")
@scodoc @scodoc

View File

@ -49,7 +49,7 @@ import os
import flask import flask
import pytest 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_formation, sco_formsemestre
from app.scodoc import sco_edit_matiere from app.scodoc import sco_edit_matiere
from app.scodoc import sco_edit_module from app.scodoc import sco_edit_module
@ -155,25 +155,21 @@ def test_formations(test_client):
formsemestre_id=formsemestre_idt, 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) formation = Formation.query.get(formation_id)
# lif est une Response car on a appelé une vue (1er appel) assert isinstance(formation, Formation)
assert isinstance(lif, flask.Response) assert formation.acronyme == f["acronyme"]
load_lif = json.loads(lif.get_data().decode("utf-8")) assert formation.titre_officiel == f["titre_officiel"]
assert len(load_lif) == 1 assert formation.id == formation_id
assert load_lif[0]["acronyme"] == f["acronyme"] assert formation.titre == f["titre"]
assert load_lif[0]["titre_officiel"] == f["titre_officiel"]
assert load_lif[0]["formation_id"] == formation_id
assert load_lif[0]["titre"] == f["titre"]
lif2 = notes.formation_list(format="json").get_data(as_text=True) f_dict = formation.to_dict()
# lif2 est un chaine assert isinstance(f_dict, dict)
assert isinstance(lif2, str) del f_dict["departement"]
load_lif2 = json.loads(lif2) # pour le test:
assert len(load_lif2) == 2 f_dict["referentiel_competence_id"] = f_dict["referentiel_competence_id"] or ""
assert load_lif2[0] == load_lif[0] assert f_dict == f
assert load_lif2[1]["titre"] == formation2["titre"]
# --- Export de formation_id # --- Export de formation_id
@ -324,10 +320,8 @@ def test_formations(test_client):
# --- Suppression d'une formation # --- Suppression d'une formation
sco_edit_formation.do_formation_delete(formation_id=formation_id2) sco_edit_formation.do_formation_delete(formation_id=formation_id2)
lif3 = notes.formation_list(format="json").get_data(as_text=True) formation = Formation.query.get(formation_id2)
assert isinstance(lif3, str) assert formation is None
load_lif3 = json.loads(lif3)
assert len(load_lif3) == 1
def test_import_formation(test_client, filename="formation-exemple-1.xml"): def test_import_formation(test_client, filename="formation-exemple-1.xml"):