MonScoDocEssai/tools/fakedatabase/create_test_api_database.py

235 lines
7.0 KiB
Python

# -*- coding: utf-8 -*-
"""Initialise une base pour les tests de l'API ScoDoc 9
Création des départements, formations, semestres, étudiants, groupes...
utilisation:
1) modifier /opt/scodoc/.env pour indiquer
FLASK_ENV=test_api
FLASK_DEBUG=1
2) En tant qu'utilisateur scodoc, lancer:
tools/create_database.sh SCODOC_TEST_API
flask db upgrade
flask sco-db-init --erase
flask init-test-database
3) relancer ScoDoc:
flask run --host 0.0.0.0
4) lancer client de test
"""
import datetime
import random
import sys
from app.auth.models import Role, User
from app import models
from app.models import Departement, Formation, FormSemestre, Identite, ModuleImpl
from app import db
from app.scodoc import (
sco_cache,
sco_evaluation_db,
sco_formations,
sco_formsemestre_inscriptions,
sco_groups,
)
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_saisie_notes import notes_add
from tools.fakeportal.gen_nomprenoms import nomprenom
random.seed(12345678) # tests reproductibles
# La formation à utiliser:
FORMATION_XML_FILENAME = "tests/ressources/formations/scodoc_formation_RT_BUT_RT_v1.xml"
def init_departement(acronym: str) -> Departement:
"Create dept, and switch context into it."
import app as mapp
dept = Departement(acronym=acronym)
db.session.add(dept)
mapp.set_sco_dept(acronym)
db.session.commit()
return dept
def import_formation() -> Formation:
"""Import formation from XML.
Returns formation_id
"""
with open(FORMATION_XML_FILENAME) as f:
doc = f.read()
# --- Création de la formation
f = sco_formations.formation_import_xml(doc)
return Formation.query.get(f[0])
def create_users(dept: Departement) -> tuple:
"""créé les utilisateurs nécessaires aux tests"""
# Un utilisateur "test" (passwd test) pouvant lire l'API
user = User(user_name="test", nom="Doe", prenom="John", dept=dept.acronym)
user.set_password("test")
db.session.add(user)
# Le rôle standard LecteurAPI existe déjà
role = Role.query.filter_by(name="LecteurAPI").first()
if role is None:
print("Erreur: rôle LecteurAPI non existant")
sys.exit(1)
perm_api_view = Permission.get_by_name("APIView")
role.add_permission(perm_api_view)
db.session.add(role)
user.add_role(role, None)
# Un utilisateur "other" n'ayant aucune permission sur l'API
other = User(user_name="other", nom="Sans", prenom="Permission", dept=dept.acronym)
other.set_password("other")
db.session.add(other)
db.session.commit()
return user, other
def create_fake_etud(dept: Departement) -> Identite:
"""Créé un faux étudiant et l'insère dans la base."""
civilite = random.choice(("M", "F", "X"))
nom, prenom = nomprenom(civilite)
etud: Identite = Identite(
civilite=civilite, nom=nom, prenom=prenom, dept_id=dept.id
)
db.session.add(etud)
db.session.commit()
# créé un étudiant sur deux avec un NIP et INE alphanumérique
etud.code_nip = f"{etud.id}" if (etud.id % 2) else f"NIP{etud.id}"
etud.code_ine = f"INE{etud.id}" if (etud.id % 2) else f"{etud.id}"
db.session.add(etud)
db.session.commit()
adresse = models.Adresse(
etudid=etud.id, email=f"{etud.prenom}.{etud.nom}@example.com"
)
db.session.add(adresse)
admission = models.Admission(etudid=etud.id)
db.session.add(admission)
db.session.commit()
return etud
def create_etuds(dept: Departement, nb=16) -> list:
"create nb etuds"
return [create_fake_etud(dept) for _ in range(nb)]
def create_formsemestre(
formation: Formation, responsable: User, semestre_idx=1
) -> FormSemestre:
"""Create formsemestre and moduleimpls
responsable: resp. du formsemestre
"""
formsemestre = FormSemestre(
dept_id=formation.dept_id,
semestre_id=semestre_idx,
titre="Semestre test",
date_debut=datetime.datetime(2021, 9, 1),
date_fin=datetime.datetime(2022, 8, 31),
modalite="FI",
formation=formation,
)
db.session.add(formsemestre)
db.session.commit()
# Crée un modulimpl par module de ce semestre:
for module in formation.modules.filter_by(semestre_id=semestre_idx):
modimpl = models.ModuleImpl(
module_id=module.id,
formsemestre_id=formsemestre.id,
responsable_id=responsable.id,
)
db.session.add(modimpl)
db.session.commit()
partition_id = sco_groups.partition_create(
formsemestre.id, default=True, redirect=False
)
_group_id = sco_groups.create_group(partition_id, default=True)
return formsemestre
def inscrit_etudiants(etuds: list, formsemestre: FormSemestre):
"""Inscrit les etudiants aux semestres et à tous ses modules"""
for etud in etuds:
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
formsemestre.id,
etud.id,
group_ids=[],
etat="I",
method="init db test",
)
def create_evaluations(formsemestre: FormSemestre):
"creation d'une evaluation dans cahque modimpl du semestre"
for modimpl in formsemestre.modimpls:
args = {
"moduleimpl_id": modimpl.id,
"jour": None,
"heure_debut": "8h00",
"heure_fin": "9h00",
"description": None,
"note_max": 20,
"coefficient": 1.0,
"visibulletin": True,
"publish_incomplete": True,
"evaluation_type": None,
"numero": None,
}
evaluation_id = sco_evaluation_db.do_evaluation_create(**args)
def saisie_note_evaluations(formsemestre: FormSemestre, user: User):
"""
Saisie les notes des evaluations d'un semestre
"""
# Récupération des id des étudiants du semestre
list_etudids = [etud.id for etud in formsemestre.etuds]
list_ues = formsemestre.query_ues()
def create_list_etudid_random_notes():
"""
Retourne une liste de tuple (etudid, note_random)
"""
return [(etudid, random.uniform(0.0, 20.0)) for etudid in list_etudids]
for ue in list_ues:
mods = ue.modules
for mod in mods:
moduleimpl = ModuleImpl.query.get_or_404(mod.id)
for evaluation in moduleimpl.evaluations:
notes = create_list_etudid_random_notes()
notes_add(user, evaluation.id, notes)
def init_test_database():
"""Appelé par la commande `flask init-test-database`
Création d'un département et de son contenu pour les tests
"""
dept = init_departement("TAPI")
user_lecteur, user_autre = create_users(dept)
with sco_cache.DeferredSemCacheManager():
etuds = create_etuds(dept)
formation = import_formation()
formsemestre = create_formsemestre(formation, user_lecteur)
create_evaluations(formsemestre)
inscrit_etudiants(etuds, formsemestre)
saisie_note_evaluations(formsemestre, user_lecteur)
# à compléter
# - groupes
# - absences
# - notes
# - décisions de jury
# ...