forked from ScoDoc/ScoDoc
Recherche étudiant: réparations et améliorations
This commit is contained in:
parent
03cea5daf7
commit
5ec598e693
@ -250,8 +250,8 @@ def referentiel_competences(formation_id: int):
|
|||||||
return formation.referentiel_competence.to_dict()
|
return formation.referentiel_competence.to_dict()
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/set_ue_parcours/<int:ue_id>", methods=["POST"])
|
@bp.route("/formation/ue/<int:ue_id>/set_parcours", methods=["POST"])
|
||||||
@api_web_bp.route("/set_ue_parcours/<int:ue_id>", methods=["POST"])
|
@api_web_bp.route("/formation/ue/<int:ue_id>/set_parcours", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.EditFormation)
|
@permission_required(Permission.EditFormation)
|
||||||
@ -280,11 +280,11 @@ def set_ue_parcours(ue_id: int):
|
|||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/assoc_ue_niveau/<int:ue_id>/<int:niveau_id>",
|
"/formation/ue/<int:ue_id>/assoc_niveau/<int:niveau_id>",
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/assoc_ue_niveau/<int:ue_id>/<int:niveau_id>",
|
"/formation/ue/<int:ue_id>/assoc_niveau/<int:niveau_id>",
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@login_required
|
@login_required
|
||||||
@ -309,11 +309,11 @@ def assoc_ue_niveau(ue_id: int, niveau_id: int):
|
|||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/desassoc_ue_niveau/<int:ue_id>",
|
"/formation/ue/<int:ue_id>/desassoc_niveau",
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/desassoc_ue_niveau/<int:ue_id>",
|
"/formation/ue/<int:ue_id>/desassoc_niveau",
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@login_required
|
@login_required
|
||||||
@ -340,8 +340,8 @@ def desassoc_ue_niveau(ue_id: int):
|
|||||||
return {"status": 0}
|
return {"status": 0}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/ue/<int:ue_id>", methods=["GET"])
|
@bp.route("/formation/ue/<int:ue_id>", methods=["GET"])
|
||||||
@api_web_bp.route("/ue/<int:ue_id>", methods=["GET"])
|
@api_web_bp.route("/formation/ue/<int:ue_id>", methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
@ -354,8 +354,8 @@ def get_ue(ue_id: int):
|
|||||||
return ue.to_dict(convert_objects=True)
|
return ue.to_dict(convert_objects=True)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/module/<int:module_id>", methods=["GET"])
|
@bp.route("/formation/module/<int:module_id>", methods=["GET"])
|
||||||
@api_web_bp.route("/module/<int:module_id>", methods=["GET"])
|
@api_web_bp.route("/formation/module/<int:module_id>", methods=["GET"])
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
@ -368,17 +368,23 @@ def get_module(module_id: int):
|
|||||||
return module.to_dict(convert_objects=True)
|
return module.to_dict(convert_objects=True)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/ue/set_code_apogee", methods=["POST"])
|
@bp.route("/formation/ue/set_code_apogee", methods=["POST"])
|
||||||
@api_web_bp.route("/ue/set_code_apogee", methods=["POST"])
|
@api_web_bp.route("/ue/set_code_apogee", methods=["POST"])
|
||||||
@bp.route("/ue/<int:ue_id>/set_code_apogee/<string:code_apogee>", methods=["POST"])
|
@bp.route(
|
||||||
|
"/formation/ue/<int:ue_id>/set_code_apogee/<string:code_apogee>", methods=["POST"]
|
||||||
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/ue/<int:ue_id>/set_code_apogee/<string:code_apogee>", methods=["POST"]
|
"/formation/ue/<int:ue_id>/set_code_apogee/<string:code_apogee>", methods=["POST"]
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/ue/<int:ue_id>/set_code_apogee", defaults={"code_apogee": ""}, methods=["POST"]
|
"/formation/ue/<int:ue_id>/set_code_apogee",
|
||||||
|
defaults={"code_apogee": ""},
|
||||||
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/ue/<int:ue_id>/set_code_apogee", defaults={"code_apogee": ""}, methods=["POST"]
|
"/formation/ue/<int:ue_id>/set_code_apogee",
|
||||||
|
defaults={"code_apogee": ""},
|
||||||
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@ -416,17 +422,21 @@ def ue_set_code_apogee(ue_id: int | None = None, code_apogee: str = ""):
|
|||||||
return code_apogee or ""
|
return code_apogee or ""
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/ue/<int:ue_id>/set_code_apogee_rcue/<string:code_apogee>", methods=["POST"])
|
@bp.route(
|
||||||
|
"/formation/ue/<int:ue_id>/set_code_apogee_rcue/<string:code_apogee>",
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/ue/<int:ue_id>/set_code_apogee_rcue/<string:code_apogee>", methods=["POST"]
|
"/formation/ue/<int:ue_id>/set_code_apogee_rcue/<string:code_apogee>",
|
||||||
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/ue/<int:ue_id>/set_code_apogee_rcue",
|
"/formation/ue/<int:ue_id>/set_code_apogee_rcue",
|
||||||
defaults={"code_apogee": ""},
|
defaults={"code_apogee": ""},
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/ue/<int:ue_id>/set_code_apogee_rcue",
|
"/formation/ue/<int:ue_id>/set_code_apogee_rcue",
|
||||||
defaults={"code_apogee": ""},
|
defaults={"code_apogee": ""},
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@ -461,23 +471,23 @@ def ue_set_code_apogee_rcue(ue_id: int, code_apogee: str = ""):
|
|||||||
return code_apogee or ""
|
return code_apogee or ""
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/module/set_code_apogee", methods=["POST"])
|
@bp.route("/formation/module/set_code_apogee", methods=["POST"])
|
||||||
@api_web_bp.route("/module/set_code_apogee", methods=["POST"])
|
@api_web_bp.route("/formation/module/set_code_apogee", methods=["POST"])
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/module/<int:module_id>/set_code_apogee/<string:code_apogee>",
|
"/formation/module/<int:module_id>/set_code_apogee/<string:code_apogee>",
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/module/<int:module_id>/set_code_apogee/<string:code_apogee>",
|
"/formation/module/<int:module_id>/set_code_apogee/<string:code_apogee>",
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"/module/<int:module_id>/set_code_apogee",
|
"/formation/module/<int:module_id>/set_code_apogee",
|
||||||
defaults={"code_apogee": ""},
|
defaults={"code_apogee": ""},
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/module/<int:module_id>/set_code_apogee",
|
"/formation/module/<int:module_id>/set_code_apogee",
|
||||||
defaults={"code_apogee": ""},
|
defaults={"code_apogee": ""},
|
||||||
methods=["POST"],
|
methods=["POST"],
|
||||||
)
|
)
|
||||||
@ -515,3 +525,54 @@ def module_set_code_apogee(module_id: int | None = None, code_apogee: str = ""):
|
|||||||
db.session.add(module)
|
db.session.add(module)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return code_apogee or ""
|
return code_apogee or ""
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(
|
||||||
|
"/formation/module/<int:module_id>/edit",
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
|
@api_web_bp.route(
|
||||||
|
"/formation/module/<int:module_id>/edit",
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.EditFormation)
|
||||||
|
@as_json
|
||||||
|
def module_edit(module_id: int):
|
||||||
|
"""Édition d'un module. Renvoie le module en json."""
|
||||||
|
query = Module.query.filter_by(id=module_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.join(Formation).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
module: Module = query.first_or_404()
|
||||||
|
args = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
|
module.from_dict(args)
|
||||||
|
db.session.commit()
|
||||||
|
db.session.refresh(module)
|
||||||
|
log(f"API module_edit: module_id={module.id} args={args}")
|
||||||
|
r = module.to_dict(convert_objects=True, with_parcours_ids=True)
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(
|
||||||
|
"/formation/ue/<int:ue_id>/edit",
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
|
@api_web_bp.route(
|
||||||
|
"/formation/ue/<int:ue_id>/edit",
|
||||||
|
methods=["POST"],
|
||||||
|
)
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.EditFormation)
|
||||||
|
@as_json
|
||||||
|
def ue_edit(ue_id: int):
|
||||||
|
"""Édition d'une UE. Renvoie l'UE en json."""
|
||||||
|
ue = UniteEns.get_ue(ue_id)
|
||||||
|
args = request.get_json(force=True) # may raise 400 Bad Request
|
||||||
|
ue.from_dict(args)
|
||||||
|
db.session.commit()
|
||||||
|
db.session.refresh(ue)
|
||||||
|
log(f"API ue_edit: ue_id={ue.id} args={args}")
|
||||||
|
r = ue.to_dict(convert_objects=True)
|
||||||
|
return r
|
||||||
|
@ -106,31 +106,74 @@ class Module(models.ScoDocModel):
|
|||||||
return args_dict
|
return args_dict
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def filter_model_attributes(cls, data: dict, excluded: set[str] = None) -> dict:
|
def filter_model_attributes(cls, args: dict, excluded: set[str] = None) -> dict:
|
||||||
"""Returns a copy of dict with only the keys belonging to the Model and not in excluded.
|
"""Returns a copy of dict with only the keys belonging to the Model and not in excluded.
|
||||||
Add 'id' to excluded."""
|
Add 'id' to excluded."""
|
||||||
# on ne peut pas affecter directement parcours
|
# on ne peut pas affecter directement parcours
|
||||||
return super().filter_model_attributes(data, (excluded or set()) | {"parcours"})
|
return super().filter_model_attributes(args, (excluded or set()) | {"parcours"})
|
||||||
|
|
||||||
|
def from_dict(self, args: dict, excluded: set[str] | None = None) -> bool:
|
||||||
|
"""Update object's fields given in dict. Add to session but don't commit.
|
||||||
|
True if modification.
|
||||||
|
- can't change ue nor formation
|
||||||
|
- can change matiere_id, iff new matiere in same ue
|
||||||
|
- can change parcours: parcours list of ApcParcour id or instances.
|
||||||
|
"""
|
||||||
|
# Vérifie les changements de matiere
|
||||||
|
new_matiere_id = args.get("matiere_id", self.matiere_id)
|
||||||
|
if new_matiere_id != self.matiere_id:
|
||||||
|
# exists ?
|
||||||
|
from app.models import Matiere
|
||||||
|
|
||||||
|
matiere = db.session.get(Matiere, new_matiere_id)
|
||||||
|
if matiere is None or matiere.ue_id != self.ue_id:
|
||||||
|
raise ScoValueError("invalid matiere")
|
||||||
|
|
||||||
|
modified = super().from_dict(
|
||||||
|
args, excluded=(excluded or set()) | {"formation_id", "ue_id"}
|
||||||
|
)
|
||||||
|
|
||||||
|
existing_parcours = {p.id for p in self.parcours}
|
||||||
|
new_parcours = args.get("parcours", []) or []
|
||||||
|
if existing_parcours != set(new_parcours):
|
||||||
|
self._set_parcours_from_list(new_parcours)
|
||||||
|
return True
|
||||||
|
return modified
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_from_dict(cls, data: dict) -> "Module":
|
def create_from_dict(cls, data: dict) -> "Module":
|
||||||
"""Create from given dict, add parcours"""
|
"""Create from given dict, add parcours"""
|
||||||
mod = super().create_from_dict(data)
|
module = super().create_from_dict(data)
|
||||||
for p in data.get("parcours", []) or []:
|
module._set_parcours_from_list(data.get("parcours", []) or [])
|
||||||
|
return module
|
||||||
|
|
||||||
|
def _set_parcours_from_list(self, parcours: list[ApcParcours | int]):
|
||||||
|
"""Ajoute ces parcours à la liste des parcours du module.
|
||||||
|
Chaque élément est soit un objet parcours soit un id.
|
||||||
|
S'assure que chaque parcours est dans le référentiel de compétence
|
||||||
|
associé à la formation du module.
|
||||||
|
"""
|
||||||
|
for p in parcours:
|
||||||
if isinstance(p, ApcParcours):
|
if isinstance(p, ApcParcours):
|
||||||
parcour: ApcParcours = p
|
parcour: ApcParcours = p
|
||||||
|
if p.referentiel_id != self.formation.referentiel_competence.id:
|
||||||
|
raise ScoValueError("Parcours hors référentiel du module")
|
||||||
else:
|
else:
|
||||||
pid = int(p)
|
try:
|
||||||
query = ApcParcours.query.filter_by(id=pid)
|
pid = int(p)
|
||||||
|
except ValueError as exc:
|
||||||
|
raise ScoValueError("id de parcours invalide") from exc
|
||||||
|
query = (
|
||||||
|
ApcParcours.query.filter_by(id=pid)
|
||||||
|
.join(ApcReferentielCompetences)
|
||||||
|
.filter_by(id=self.formation.referentiel_competence.id)
|
||||||
|
)
|
||||||
if g.scodoc_dept:
|
if g.scodoc_dept:
|
||||||
query = query.join(ApcReferentielCompetences).filter_by(
|
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
dept_id=g.scodoc_dept_id
|
|
||||||
)
|
|
||||||
parcour: ApcParcours = query.first()
|
parcour: ApcParcours = query.first()
|
||||||
if parcour is None:
|
if parcour is None:
|
||||||
raise ScoValueError("Parcours invalide")
|
raise ScoValueError("Parcours invalide")
|
||||||
mod.parcours.append(parcour)
|
self.parcours.append(parcour)
|
||||||
return mod
|
|
||||||
|
|
||||||
def clone(self):
|
def clone(self):
|
||||||
"""Create a new copy of this module."""
|
"""Create a new copy of this module."""
|
||||||
@ -163,14 +206,25 @@ class Module(models.ScoDocModel):
|
|||||||
mod.app_critiques.append(app_critique)
|
mod.app_critiques.append(app_critique)
|
||||||
return mod
|
return mod
|
||||||
|
|
||||||
def to_dict(self, convert_objects=False, with_matiere=False, with_ue=False) -> dict:
|
def to_dict(
|
||||||
|
self,
|
||||||
|
convert_objects=False,
|
||||||
|
with_matiere=False,
|
||||||
|
with_ue=False,
|
||||||
|
with_parcours_ids=False,
|
||||||
|
) -> dict:
|
||||||
"""If convert_objects, convert all attributes to native types
|
"""If convert_objects, convert all attributes to native types
|
||||||
(suitable jor json encoding).
|
(suitable jor json encoding).
|
||||||
|
If convert_objects and with_parcours_ids, give parcours as a list of id (API)
|
||||||
"""
|
"""
|
||||||
d = dict(self.__dict__)
|
d = dict(self.__dict__)
|
||||||
d.pop("_sa_instance_state", None)
|
d.pop("_sa_instance_state", None)
|
||||||
|
d.pop("formation", None)
|
||||||
if convert_objects:
|
if convert_objects:
|
||||||
d["parcours"] = [p.to_dict() for p in self.parcours]
|
if with_parcours_ids:
|
||||||
|
d["parcours"] = [p.id for p in self.parcours]
|
||||||
|
else:
|
||||||
|
d["parcours"] = [p.to_dict() for p in self.parcours]
|
||||||
d["ue_coefs"] = [
|
d["ue_coefs"] = [
|
||||||
c.to_dict(convert_objects=convert_objects) for c in self.ue_coefs
|
c.to_dict(convert_objects=convert_objects) for c in self.ue_coefs
|
||||||
]
|
]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""ScoDoc 9 models : Unités d'Enseignement (UE)
|
"""ScoDoc 9 models : Unités d'Enseignement (UE)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from flask import g
|
from flask import abort, g
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from app import db, log
|
from app import db, log
|
||||||
@ -123,6 +123,16 @@ class UniteEns(models.ScoDocModel):
|
|||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
def from_dict(self, args: dict, excluded: set[str] | None = None) -> bool:
|
||||||
|
"""Update object's fields given in dict. Add to session but don't commit.
|
||||||
|
True if modification.
|
||||||
|
- can't change formation nor niveau_competence
|
||||||
|
"""
|
||||||
|
return super().from_dict(
|
||||||
|
args,
|
||||||
|
excluded=(excluded or set()) | {"formation_id", "niveau_competence_id"},
|
||||||
|
)
|
||||||
|
|
||||||
def to_dict(self, convert_objects=False, with_module_ue_coefs=True):
|
def to_dict(self, convert_objects=False, with_module_ue_coefs=True):
|
||||||
"""as a dict, with the same conversions as in ScoDoc7.
|
"""as a dict, with the same conversions as in ScoDoc7.
|
||||||
If convert_objects, convert all attributes to native types
|
If convert_objects, convert all attributes to native types
|
||||||
@ -255,6 +265,30 @@ class UniteEns(models.ScoDocModel):
|
|||||||
log(f"ue.set_ects( ue_id={self.id}, acronyme={self.acronyme}, ects={ects} )")
|
log(f"ue.set_ects( ue_id={self.id}, acronyme={self.acronyme}, ects={ects} )")
|
||||||
db.session.add(self)
|
db.session.add(self)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_ue(cls, ue_id: int, accept_none=False) -> "UniteEns":
|
||||||
|
"""UE ou 404 (ou None si accept_none),
|
||||||
|
cherche uniquement dans le département courant.
|
||||||
|
Si accept_none, return None si l'id est invalide ou inexistant.
|
||||||
|
"""
|
||||||
|
if not isinstance(ue_id, int):
|
||||||
|
try:
|
||||||
|
ue_id = int(ue_id)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
if accept_none:
|
||||||
|
return None
|
||||||
|
abort(404, "ue_id invalide")
|
||||||
|
|
||||||
|
query = cls.query.filter_by(id=ue_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
from app.models import Formation
|
||||||
|
|
||||||
|
query = query.join(Formation).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
|
if accept_none:
|
||||||
|
return query.first()
|
||||||
|
return query.first_or_404()
|
||||||
|
|
||||||
def get_ressources(self):
|
def get_ressources(self):
|
||||||
"Liste des modules ressources rattachés à cette UE"
|
"Liste des modules ressources rattachés à cette UE"
|
||||||
return self.modules.filter_by(module_type=scu.ModuleType.RESSOURCE).all()
|
return self.modules.filter_by(module_type=scu.ModuleType.RESSOURCE).all()
|
||||||
|
@ -97,6 +97,7 @@ _HTML_BEGIN = f"""<!DOCTYPE html>
|
|||||||
|
|
||||||
<link href="{scu.STATIC_DIR}/css/scodoc.css" rel="stylesheet" type="text/css" />
|
<link href="{scu.STATIC_DIR}/css/scodoc.css" rel="stylesheet" type="text/css" />
|
||||||
<link href="{scu.STATIC_DIR}/css/menu.css" rel="stylesheet" type="text/css" />
|
<link href="{scu.STATIC_DIR}/css/menu.css" rel="stylesheet" type="text/css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="{scu.STATIC_DIR}/DataTables/datatables.min.css" />
|
||||||
<script src="{scu.STATIC_DIR}/libjs/menu.js"></script>
|
<script src="{scu.STATIC_DIR}/libjs/menu.js"></script>
|
||||||
<script src="{scu.STATIC_DIR}/libjs/bubble.js"></script>
|
<script src="{scu.STATIC_DIR}/libjs/bubble.js"></script>
|
||||||
<script>
|
<script>
|
||||||
@ -115,6 +116,7 @@ _HTML_BEGIN = f"""<!DOCTYPE html>
|
|||||||
<script src="{scu.STATIC_DIR}/libjs/jquery.field.min.js"></script>
|
<script src="{scu.STATIC_DIR}/libjs/jquery.field.min.js"></script>
|
||||||
|
|
||||||
<script src="{scu.STATIC_DIR}/libjs/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.min.js"></script>
|
<script src="{scu.STATIC_DIR}/libjs/jquery-ui-1.10.4.custom/js/jquery-ui-1.10.4.custom.min.js"></script>
|
||||||
|
<script src="{scu.STATIC_DIR}/DataTables/datatables.min.js"></script>
|
||||||
|
|
||||||
<script src="{scu.STATIC_DIR}/libjs/qtip/jquery.qtip-3.0.3.min.js"></script>
|
<script src="{scu.STATIC_DIR}/libjs/qtip/jquery.qtip-3.0.3.min.js"></script>
|
||||||
<link type="text/css" rel="stylesheet" href="{scu.STATIC_DIR}/libjs/qtip/jquery.qtip-3.0.3.min.css" />
|
<link type="text/css" rel="stylesheet" href="{scu.STATIC_DIR}/libjs/qtip/jquery.qtip-3.0.3.min.css" />
|
||||||
|
@ -30,8 +30,9 @@
|
|||||||
import flask
|
import flask
|
||||||
from flask import url_for, g, request
|
from flask import url_for, g, request
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
import app
|
from app import db
|
||||||
from app.models import Departement, Identite
|
from app.models import Departement, Identite
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
@ -101,9 +102,12 @@ def form_search_etud(
|
|||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
|
||||||
def search_etuds_infos_from_exp(expnom: str = "") -> list[Identite]:
|
def search_etuds_infos_from_exp(
|
||||||
|
expnom: str = "", dept_id: int | None = None
|
||||||
|
) -> list[Identite]:
|
||||||
"""Cherche étudiants, expnom peut être, dans cet ordre:
|
"""Cherche étudiants, expnom peut être, dans cet ordre:
|
||||||
un etudid (int), un code NIP, ou une partie d'un nom (case insensitive).
|
un etudid (int), un code NIP, ou une partie d'un nom (case insensitive).
|
||||||
|
Si dept_id est None, cherche dans le dept courant, sinon cherche dans le dept indiqué.
|
||||||
"""
|
"""
|
||||||
if not isinstance(expnom, int) and len(expnom) <= 1:
|
if not isinstance(expnom, int) and len(expnom) <= 1:
|
||||||
return [] # si expnom est trop court, n'affiche rien
|
return [] # si expnom est trop court, n'affiche rien
|
||||||
@ -111,23 +115,31 @@ def search_etuds_infos_from_exp(expnom: str = "") -> list[Identite]:
|
|||||||
etudid = int(expnom)
|
etudid = int(expnom)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
etudid = None
|
etudid = None
|
||||||
|
dept_id = g.scodoc_dept_id if dept_id is None else dept_id
|
||||||
if etudid is not None:
|
if etudid is not None:
|
||||||
etud = Identite.query.filter_by(dept_id=g.scodoc_dept_id, id=etudid).first()
|
etud = Identite.query.filter_by(dept_id=dept_id, id=etudid).first()
|
||||||
if etud:
|
if etud:
|
||||||
return [etud]
|
return [etud]
|
||||||
expnom_str = str(expnom)
|
expnom_str = str(expnom)
|
||||||
if scu.is_valid_code_nip(expnom_str):
|
if scu.is_valid_code_nip(expnom_str):
|
||||||
etuds = Identite.query.filter_by(
|
etuds = sorted(
|
||||||
dept_id=g.scodoc_dept_id, code_nip=expnom_str
|
Identite.query.filter_by(dept_id=dept_id, code_nip=expnom_str).all(),
|
||||||
).all()
|
key=lambda e: e.sort_key,
|
||||||
|
)
|
||||||
if etuds:
|
if etuds:
|
||||||
return etuds
|
return etuds
|
||||||
|
try:
|
||||||
return (
|
return sorted(
|
||||||
Identite.query.filter_by(dept_id=g.scodoc_dept_id)
|
Identite.query.filter_by(dept_id=dept_id)
|
||||||
.filter(Identite.nom.op("~*")(expnom_str))
|
.filter(
|
||||||
.all()
|
Identite.nom.op("~*")(expnom_str)
|
||||||
)
|
) # ~* matches regular expression, case-insensitive
|
||||||
|
.all(),
|
||||||
|
key=lambda e: e.sort_key,
|
||||||
|
)
|
||||||
|
except sa.exc.DataError:
|
||||||
|
db.session.rollback()
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def search_etud_in_dept(expnom=""):
|
def search_etud_in_dept(expnom=""):
|
||||||
@ -191,7 +203,7 @@ def search_etud_in_dept(expnom=""):
|
|||||||
# Choix dans la liste des résultats:
|
# Choix dans la liste des résultats:
|
||||||
rows = []
|
rows = []
|
||||||
e: Identite
|
e: Identite
|
||||||
for e in etuds:
|
for e in sorted(etuds, key=lambda e: e.sort_key):
|
||||||
url_args["etudid"] = e.id
|
url_args["etudid"] = e.id
|
||||||
target = url_for(endpoint, **url_args)
|
target = url_for(endpoint, **url_args)
|
||||||
cur_inscription = e.inscription_courante()
|
cur_inscription = e.inscription_courante()
|
||||||
@ -219,6 +231,7 @@ def search_etud_in_dept(expnom=""):
|
|||||||
"inscription_target": target,
|
"inscription_target": target,
|
||||||
"groupes": groupes,
|
"groupes": groupes,
|
||||||
"nomprenom": e.nomprenom,
|
"nomprenom": e.nomprenom,
|
||||||
|
"_nomprenom_order": e.sort_key,
|
||||||
"_nomprenom_target": target,
|
"_nomprenom_target": target,
|
||||||
"_nomprenom_td_attrs": f'id="{e.id}" class="etudinfo"',
|
"_nomprenom_td_attrs": f'id="{e.id}" class="etudinfo"',
|
||||||
}
|
}
|
||||||
@ -287,71 +300,36 @@ def search_etud_by_name(term: str) -> list:
|
|||||||
{ "label" : "<nip> <nom> <prenom>", "value" : etudid }
|
{ "label" : "<nip> <nom> <prenom>", "value" : etudid }
|
||||||
"""
|
"""
|
||||||
may_be_nip = scu.is_valid_code_nip(term)
|
may_be_nip = scu.is_valid_code_nip(term)
|
||||||
# term = term.upper() # conserve les accents
|
etuds = search_etuds_infos_from_exp(term)
|
||||||
term = term.upper()
|
|
||||||
if (
|
|
||||||
not scu.ALPHANUM_EXP.match(term) # n'autorise pas les caractères spéciaux
|
|
||||||
and not may_be_nip
|
|
||||||
):
|
|
||||||
data = []
|
|
||||||
else:
|
|
||||||
if may_be_nip:
|
|
||||||
r = ndb.SimpleDictFetch(
|
|
||||||
"""SELECT nom, prenom, code_nip
|
|
||||||
FROM identite
|
|
||||||
WHERE
|
|
||||||
dept_id = %(dept_id)s
|
|
||||||
AND code_nip ILIKE %(beginning)s
|
|
||||||
ORDER BY nom
|
|
||||||
""",
|
|
||||||
{"beginning": term + "%", "dept_id": g.scodoc_dept_id},
|
|
||||||
)
|
|
||||||
data = [
|
|
||||||
{
|
|
||||||
"label": "%s %s %s"
|
|
||||||
% (x["code_nip"], x["nom"], scu.format_prenom(x["prenom"])),
|
|
||||||
"value": x["code_nip"],
|
|
||||||
}
|
|
||||||
for x in r
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
r = ndb.SimpleDictFetch(
|
|
||||||
"""SELECT id AS etudid, nom, prenom
|
|
||||||
FROM identite
|
|
||||||
WHERE
|
|
||||||
dept_id = %(dept_id)s
|
|
||||||
AND nom ILIKE %(beginning)s
|
|
||||||
ORDER BY nom
|
|
||||||
""",
|
|
||||||
{"beginning": term + "%", "dept_id": g.scodoc_dept_id},
|
|
||||||
)
|
|
||||||
|
|
||||||
data = [
|
return [
|
||||||
{
|
{
|
||||||
"label": "%s %s" % (x["nom"], scu.format_prenom(x["prenom"])),
|
"label": f"""{(etud.code_nip+' ') if {etud.code_nip and may_be_nip} else ""}{
|
||||||
"value": x["etudid"],
|
etud.nom_prenom()}""",
|
||||||
}
|
"value": etud.id,
|
||||||
for x in r
|
}
|
||||||
]
|
for etud in etuds
|
||||||
return data
|
]
|
||||||
|
|
||||||
|
|
||||||
# ---------- Recherche sur plusieurs département
|
# ---------- Recherche sur plusieurs département
|
||||||
|
|
||||||
|
|
||||||
def search_etud_in_accessible_depts(expnom=None, code_nip=None):
|
def search_etud_in_accessible_depts(
|
||||||
|
expnom=None,
|
||||||
|
) -> tuple[list[list[Identite]], list[str]]:
|
||||||
"""
|
"""
|
||||||
result is a list of (sorted) etuds, one list per dept.
|
result: list of (sorted) etuds, one list per dept.
|
||||||
|
accessible_depts: list of dept acronyms
|
||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
accessible_depts = []
|
accessible_depts = []
|
||||||
depts = Departement.query.filter_by(visible=True).all()
|
depts = Departement.query.filter_by(visible=True).all()
|
||||||
for dept in depts:
|
for dept in depts:
|
||||||
if current_user.has_permission(Permission.ScoView, dept=dept.acronym):
|
if current_user.has_permission(Permission.ScoView, dept=dept.acronym):
|
||||||
if expnom or code_nip:
|
if expnom:
|
||||||
accessible_depts.append(dept.acronym)
|
accessible_depts.append(dept.acronym)
|
||||||
app.set_sco_dept(dept.acronym)
|
etuds = search_etuds_infos_from_exp(expnom=expnom, dept_id=dept.id)
|
||||||
etuds = search_etuds_infos(expnom=expnom, code_nip=code_nip)
|
|
||||||
else:
|
else:
|
||||||
etuds = []
|
etuds = []
|
||||||
result.append(etuds)
|
result.append(etuds)
|
||||||
@ -371,21 +349,26 @@ def table_etud_in_accessible_depts(expnom=None):
|
|||||||
]
|
]
|
||||||
for etuds in result:
|
for etuds in result:
|
||||||
if etuds:
|
if etuds:
|
||||||
dept_id = etuds[0]["dept"]
|
dept = etuds[0].departement
|
||||||
# H.append('<h3>Département %s</h3>' % DeptId)
|
rows = [
|
||||||
for e in etuds:
|
{
|
||||||
e["_nomprenom_target"] = url_for(
|
"nomprenom": etud.nom_prenom(),
|
||||||
"scolar.fiche_etud", scodoc_dept=dept_id, etudid=e["etudid"]
|
"_nomprenom_target": url_for(
|
||||||
)
|
"scolar.fiche_etud", scodoc_dept=dept.acronym, etudid=etud.id
|
||||||
e["_nomprenom_td_attrs"] = f"""id="{e['etudid']}" class="etudinfo" """
|
),
|
||||||
|
"_nomprenom_td_attrs": f"""id="{etud.id}" class="etudinfo" """,
|
||||||
|
"_nomprenom_order": etud.sort_key,
|
||||||
|
}
|
||||||
|
for etud in etuds
|
||||||
|
]
|
||||||
|
|
||||||
tab = GenTable(
|
tab = GenTable(
|
||||||
titles={"nomprenom": "Étudiants en " + dept_id},
|
titles={"nomprenom": "Étudiants en " + dept.acronym},
|
||||||
columns_ids=("nomprenom",),
|
columns_ids=("nomprenom",),
|
||||||
rows=etuds,
|
rows=rows,
|
||||||
html_sortable=True,
|
html_sortable=True,
|
||||||
html_class="table_leftalign",
|
html_class="table_leftalign",
|
||||||
table_id="etud_in_accessible_depts",
|
# table_id="etud_in_accessible_depts",
|
||||||
)
|
)
|
||||||
|
|
||||||
H.append('<div class="table_etud_in_dept">')
|
H.append('<div class="table_etud_in_dept">')
|
||||||
@ -410,48 +393,3 @@ def table_etud_in_accessible_depts(expnom=None):
|
|||||||
+ "\n".join(H)
|
+ "\n".join(H)
|
||||||
+ html_sco_header.standard_html_footer()
|
+ html_sco_header.standard_html_footer()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def search_inscr_etud_by_nip(code_nip, fmt="json"):
|
|
||||||
"""Recherche multi-departement d'un étudiant par son code NIP
|
|
||||||
Seuls les départements accessibles par l'utilisateur sont cherchés.
|
|
||||||
|
|
||||||
Renvoie une liste des inscriptions de l'étudiants dans tout ScoDoc:
|
|
||||||
code_nip, nom, prenom, civilite_str, dept, formsemestre_id, date_debut_sem, date_fin_sem
|
|
||||||
"""
|
|
||||||
result, _ = search_etud_in_accessible_depts(code_nip=code_nip)
|
|
||||||
|
|
||||||
rows = []
|
|
||||||
for etuds in result:
|
|
||||||
if etuds:
|
|
||||||
dept_id = etuds[0]["dept"]
|
|
||||||
for e in etuds:
|
|
||||||
for sem in e["sems"]:
|
|
||||||
rows.append(
|
|
||||||
{
|
|
||||||
"dept": dept_id,
|
|
||||||
"etudid": e["etudid"],
|
|
||||||
"code_nip": e["code_nip"],
|
|
||||||
"civilite_str": e["civilite_str"],
|
|
||||||
"nom": e["nom"],
|
|
||||||
"prenom": e["prenom"],
|
|
||||||
"formsemestre_id": sem["formsemestre_id"],
|
|
||||||
"date_debut_iso": sem["date_debut_iso"],
|
|
||||||
"date_fin_iso": sem["date_fin_iso"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
columns_ids = (
|
|
||||||
"dept",
|
|
||||||
"etudid",
|
|
||||||
"code_nip",
|
|
||||||
"civilite_str",
|
|
||||||
"nom",
|
|
||||||
"prenom",
|
|
||||||
"formsemestre_id",
|
|
||||||
"date_debut_iso",
|
|
||||||
"date_fin_iso",
|
|
||||||
)
|
|
||||||
tab = GenTable(columns_ids=columns_ids, rows=rows, table_id="inscr_etud_by_nip")
|
|
||||||
|
|
||||||
return tab.make_page(fmt=fmt, with_html_headers=False, publish=True)
|
|
||||||
|
@ -14,6 +14,9 @@ function get_etudid_from_elem(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$().ready(function () {
|
$().ready(function () {
|
||||||
|
if (typeof SCO_URL == 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var elems = $(".etudinfo:not(th)");
|
var elems = $(".etudinfo:not(th)");
|
||||||
|
|
||||||
var q_args = get_query_args();
|
var q_args = get_query_args();
|
||||||
@ -35,11 +38,7 @@ $().ready(function () {
|
|||||||
$(elems[i]).qtip({
|
$(elems[i]).qtip({
|
||||||
content: {
|
content: {
|
||||||
ajax: {
|
ajax: {
|
||||||
url:
|
url: `${SCO_URL}etud_info_html?etudid=` + get_etudid_from_elem(elems[i]) + qs,
|
||||||
SCO_URL +
|
|
||||||
"etud_info_html?etudid=" +
|
|
||||||
get_etudid_from_elem(elems[i]) +
|
|
||||||
qs,
|
|
||||||
type: "GET",
|
type: "GET",
|
||||||
//success: function(data, status) {
|
//success: function(data, status) {
|
||||||
// this.set('content.text', data);
|
// this.set('content.text', data);
|
||||||
|
@ -6,7 +6,7 @@ $(function () {
|
|||||||
delay: 300, // wait 300ms before suggestions
|
delay: 300, // wait 300ms before suggestions
|
||||||
minLength: 2, // min nb of chars before suggest
|
minLength: 2, // min nb of chars before suggest
|
||||||
position: { collision: "flip" }, // automatic menu position up/down
|
position: { collision: "flip" }, // automatic menu position up/down
|
||||||
source: SCO_URL + "search_etud_by_name",
|
source: (typeof SCO_URL !== 'undefined' && SCO_URL) ? `${SCO_URL}search_etud_by_name` : "",
|
||||||
select: function (event, ui) {
|
select: function (event, ui) {
|
||||||
$(".in-expnom").val(ui.item.value);
|
$(".in-expnom").val(ui.item.value);
|
||||||
$("#form-chercheetud").submit();
|
$("#form-chercheetud").submit();
|
||||||
|
@ -567,27 +567,6 @@ def get_etud_dept():
|
|||||||
return Departement.query.get_or_404(last_etud.dept_id).acronym
|
return Departement.query.get_or_404(last_etud.dept_id).acronym
|
||||||
|
|
||||||
|
|
||||||
# Bricolage pour le portail IUTV avec ScoDoc 7: (DEPRECATED: NE PAS UTILISER !)
|
|
||||||
@bp.route(
|
|
||||||
"/ScoDoc/search_inscr_etud_by_nip", methods=["GET"]
|
|
||||||
) # pour compat anciens clients PHP
|
|
||||||
@scodoc
|
|
||||||
@scodoc7func
|
|
||||||
def search_inscr_etud_by_nip(code_nip, fmt="json", __ac_name="", __ac_password=""):
|
|
||||||
auth_ok = False
|
|
||||||
user_name = __ac_name
|
|
||||||
user_password = __ac_password
|
|
||||||
if user_name and user_password:
|
|
||||||
u = User.query.filter_by(user_name=user_name).first()
|
|
||||||
if u and u.check_password(user_password):
|
|
||||||
auth_ok = True
|
|
||||||
flask_login.login_user(u)
|
|
||||||
if not auth_ok:
|
|
||||||
abort(403)
|
|
||||||
else:
|
|
||||||
return sco_find_etud.search_inscr_etud_by_nip(code_nip=code_nip, fmt=fmt)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/ScoDoc/about")
|
@bp.route("/ScoDoc/about")
|
||||||
@bp.route("/ScoDoc/Scolarite/<scodoc_dept>/about")
|
@bp.route("/ScoDoc/Scolarite/<scodoc_dept>/about")
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -531,6 +531,9 @@ sco_publish(
|
|||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
@as_json
|
@as_json
|
||||||
def search_etud_by_name():
|
def search_etud_by_name():
|
||||||
|
"""Recherche étudiants par nom ou NIP
|
||||||
|
utilisé par autocomplete formulaire recherche
|
||||||
|
"""
|
||||||
term = request.args["term"]
|
term = request.args["term"]
|
||||||
data = sco_find_etud.search_etud_by_name(term)
|
data = sco_find_etud.search_etud_by_name(term)
|
||||||
return data
|
return data
|
||||||
|
@ -331,36 +331,116 @@ def test_referentiel_competences(api_headers):
|
|||||||
|
|
||||||
def test_api_ue_apo(api_admin_headers):
|
def test_api_ue_apo(api_admin_headers):
|
||||||
"""Routes
|
"""Routes
|
||||||
/ue/<int:ue_id>
|
/formation/ue/<int:ue_id>
|
||||||
/ue/<int:ue_id>/set_code_apogee/<string:code_apogee>
|
/formation/ue/<int:ue_id>/set_code_apogee/<string:code_apogee>
|
||||||
/ue/<int:ue_id>/set_code_apogee_rcue/<string:code_apogee>
|
/formation/ue/<int:ue_id>/set_code_apogee_rcue/<string:code_apogee>
|
||||||
"""
|
"""
|
||||||
ue_id = 1
|
ue_id = 1
|
||||||
ue = GET(path=f"/ue/{ue_id}", headers=api_admin_headers)
|
ue = GET(path=f"/formation/ue/{ue_id}", headers=api_admin_headers)
|
||||||
assert ue["id"] == ue_id
|
assert ue["id"] == ue_id
|
||||||
r = POST_JSON(f"/ue/{ue_id}/set_code_apogee/APOUE", {}, api_admin_headers, raw=True)
|
r = POST_JSON(
|
||||||
|
f"/formation/ue/{ue_id}/set_code_apogee/APOUE", {}, api_admin_headers, raw=True
|
||||||
|
)
|
||||||
assert r.text == "APOUE"
|
assert r.text == "APOUE"
|
||||||
r = POST_JSON(
|
r = POST_JSON(
|
||||||
f"/ue/{ue_id}/set_code_apogee_rcue/APORCUE", {}, api_admin_headers, raw=True
|
f"/formation/ue/{ue_id}/set_code_apogee_rcue/APORCUE",
|
||||||
|
{},
|
||||||
|
api_admin_headers,
|
||||||
|
raw=True,
|
||||||
)
|
)
|
||||||
assert r.text == "APORCUE"
|
assert r.text == "APORCUE"
|
||||||
ue = GET(path=f"/ue/{ue_id}", headers=api_admin_headers)
|
ue = GET(path=f"/formation/ue/{ue_id}", headers=api_admin_headers)
|
||||||
assert ue["code_apogee"] == "APOUE"
|
assert ue["code_apogee"] == "APOUE"
|
||||||
assert ue["code_apogee_rcue"] == "APORCUE"
|
assert ue["code_apogee_rcue"] == "APORCUE"
|
||||||
|
|
||||||
|
|
||||||
def test_api_module_apo(api_admin_headers):
|
def test_api_module_apo(api_admin_headers):
|
||||||
"""Routes
|
"""Routes
|
||||||
/module/<int:module_id>
|
/formation/module/<int:module_id>
|
||||||
/module/<int:module_id>/set_code_apogee/<string:code_apogee>
|
/formation/module/<int:module_id>/set_code_apogee/<string:code_apogee>
|
||||||
"""
|
"""
|
||||||
module_id = 1
|
module_id = 1
|
||||||
module = GET(path=f"/module/{module_id}", headers=api_admin_headers)
|
module = GET(path=f"/formation/module/{module_id}", headers=api_admin_headers)
|
||||||
assert module["id"] == module_id
|
assert module["id"] == module_id
|
||||||
assert module["code_apogee"] == ""
|
assert module["code_apogee"] == ""
|
||||||
r = POST_JSON(
|
r = POST_JSON(
|
||||||
f"/module/{module_id}/set_code_apogee/APOMOD", {}, api_admin_headers, raw=True
|
f"/formation/module/{module_id}/set_code_apogee/APOMOD",
|
||||||
|
{},
|
||||||
|
api_admin_headers,
|
||||||
|
raw=True,
|
||||||
)
|
)
|
||||||
assert r.text == "APOMOD"
|
assert r.text == "APOMOD"
|
||||||
module = GET(path=f"/module/{module_id}", headers=api_admin_headers)
|
module = GET(path=f"/formation/module/{module_id}", headers=api_admin_headers)
|
||||||
assert module["code_apogee"] == "APOMOD"
|
assert module["code_apogee"] == "APOMOD"
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_module_edit(api_admin_headers):
|
||||||
|
"""Routes
|
||||||
|
/formation/module/<int:module_id>/edit
|
||||||
|
"""
|
||||||
|
module_id = 1
|
||||||
|
module = POST_JSON(
|
||||||
|
f"/formation/module/{module_id}/edit",
|
||||||
|
{"heures_cours": 16, "semestre_id": 1, "abbrev": "ALLO"},
|
||||||
|
api_admin_headers,
|
||||||
|
)
|
||||||
|
assert module["id"] == module_id
|
||||||
|
assert module["heures_cours"] == 16
|
||||||
|
assert module["semestre_id"] == 1
|
||||||
|
assert module["abbrev"] == "ALLO"
|
||||||
|
# tente de changer l'UE: ne devrait rien faire:
|
||||||
|
ue_id = module["ue_id"]
|
||||||
|
module = POST_JSON(
|
||||||
|
f"/formation/module/{module_id}/edit",
|
||||||
|
{"ue_id": 666},
|
||||||
|
api_admin_headers,
|
||||||
|
)
|
||||||
|
assert module["ue_id"] == ue_id
|
||||||
|
# tente de changer la formation: ne devrait rien faire:
|
||||||
|
formation_id = module["formation_id"]
|
||||||
|
module = POST_JSON(
|
||||||
|
f"/formation/module/{module_id}/edit",
|
||||||
|
{"formation_id": 666},
|
||||||
|
api_admin_headers,
|
||||||
|
)
|
||||||
|
assert module["formation_id"] == formation_id
|
||||||
|
# -- assignation de parcours (ce test suppose que les parcours 1, 2, 3 existent)
|
||||||
|
assert module["parcours"] == []
|
||||||
|
module = POST_JSON(
|
||||||
|
f"/formation/module/{module_id}/edit",
|
||||||
|
{"parcours": [1, 2, 3]},
|
||||||
|
api_admin_headers,
|
||||||
|
)
|
||||||
|
assert sorted(module["parcours"]) == [1, 2, 3]
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_ue_edit(api_admin_headers):
|
||||||
|
"""Routes
|
||||||
|
/formation/ue/<int:ue_id>/edit
|
||||||
|
"""
|
||||||
|
ue_id = 1
|
||||||
|
ue = POST_JSON(
|
||||||
|
f"/formation/ue/{ue_id}/edit",
|
||||||
|
{"titre": "formation test modifiée", "numero": 22},
|
||||||
|
api_admin_headers,
|
||||||
|
)
|
||||||
|
assert ue["id"] == ue_id
|
||||||
|
assert ue["numero"] == 22
|
||||||
|
assert ue["titre"] == "formation test modifiée"
|
||||||
|
|
||||||
|
# tente de changer le niveau de compétence: ne devrait rien faire:
|
||||||
|
niveau_competence_id = ue["niveau_competence_id"]
|
||||||
|
ue = POST_JSON(
|
||||||
|
f"/formation/ue/{ue_id}/edit",
|
||||||
|
{"niveau_competence_id": 666},
|
||||||
|
api_admin_headers,
|
||||||
|
)
|
||||||
|
assert ue["niveau_competence_id"] == niveau_competence_id
|
||||||
|
# tente de changer la formation: ne devrait rien faire:
|
||||||
|
formation_id = ue["formation_id"]
|
||||||
|
ue = POST_JSON(
|
||||||
|
f"/formation/ue/{ue_id}/edit",
|
||||||
|
{"formation_id": 666},
|
||||||
|
api_admin_headers,
|
||||||
|
)
|
||||||
|
assert ue["formation_id"] == formation_id
|
||||||
|
Loading…
Reference in New Issue
Block a user