forked from ScoDoc/DocScoDoc
533 lines
17 KiB
Python
533 lines
17 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
|
|
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 time
|
|
import sys
|
|
|
|
from app.auth.models import Role, User
|
|
from app import models
|
|
from app.models import (
|
|
Departement,
|
|
Formation,
|
|
FormSemestre,
|
|
Identite,
|
|
ModuleImpl,
|
|
NotesNotes,
|
|
ApcReferentielCompetences,
|
|
ApcCompetence,
|
|
Absence,
|
|
FormSemestreEtape,
|
|
)
|
|
from app import db
|
|
from app.models.but_refcomp import (
|
|
ApcParcours,
|
|
ApcAnneeParcours,
|
|
ApcSituationPro,
|
|
ApcComposanteEssentielle,
|
|
ApcNiveau,
|
|
ApcAppCritique,
|
|
)
|
|
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:
|
|
aleatoire = random.randint(0, 10)
|
|
if aleatoire <= 3:
|
|
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
|
|
formsemestre.id,
|
|
etud.id,
|
|
group_ids=[],
|
|
etat="I",
|
|
method="init db test",
|
|
)
|
|
elif 3 < aleatoire <= 6:
|
|
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
|
|
formsemestre.id,
|
|
etud.id,
|
|
group_ids=[],
|
|
etat="D",
|
|
method="init db test",
|
|
)
|
|
else:
|
|
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
|
|
formsemestre.id,
|
|
etud.id,
|
|
group_ids=[],
|
|
etat="DEF",
|
|
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_notes_evaluations(formsemestre: FormSemestre, user: User):
|
|
"""
|
|
Saisie les notes des evaluations d'un semestre
|
|
"""
|
|
etuds = formsemestre.etuds
|
|
list_etuds = []
|
|
for etu in etuds:
|
|
list_etuds.append(etu)
|
|
|
|
date_debut = formsemestre.date_debut
|
|
date_fin = formsemestre.date_fin
|
|
|
|
list_ues = formsemestre.query_ues()
|
|
|
|
def saisir_notes(evaluation_id: int, condition: int):
|
|
"""
|
|
Permet de saisir les notes de manière aléatoire suivant une condition
|
|
Définition des valeurs de condition :
|
|
0 : all_notes_saisies
|
|
1 : all_notes_manquantes
|
|
2 : some_notes_manquantes
|
|
"""
|
|
if condition == 0 or condition == 2:
|
|
if condition == 0:
|
|
for etu in list_etuds:
|
|
note = NotesNotes(
|
|
etu.id,
|
|
evaluation_id,
|
|
random.uniform(0, 20),
|
|
"",
|
|
date_debut + random.random() * (date_fin - date_debut),
|
|
user.id,
|
|
)
|
|
db.session.add(note)
|
|
db.session.commit()
|
|
else:
|
|
percent = 80 / 100
|
|
len_etuds = len(list_etuds)
|
|
new_list_etuds = random.sample(list_etuds, k=int(percent * len_etuds))
|
|
for etu in new_list_etuds:
|
|
note = NotesNotes(
|
|
etu.id,
|
|
evaluation_id,
|
|
random.uniform(0, 20),
|
|
"",
|
|
date_debut + random.random() * (date_fin - date_debut),
|
|
user.id,
|
|
)
|
|
db.session.add(note)
|
|
db.session.commit()
|
|
|
|
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:
|
|
condition_saisie_notes = random.randint(0, 2)
|
|
saisir_notes(evaluation.id, condition_saisie_notes)
|
|
|
|
|
|
def create_ref_comp(formation: Formation):
|
|
"""
|
|
Créer un referentiel de competences
|
|
"""
|
|
# ### ApcSituationPro ###
|
|
# apc_situation_pro_id = 1
|
|
# apc_situation_pro_competence_id = 1
|
|
# apc_situation_pro_libelle = ""
|
|
#
|
|
# apc_situation_pro = ApcSituationPro(
|
|
# apc_situation_pro_id, apc_situation_pro_competence_id, apc_situation_pro_libelle
|
|
# )
|
|
# db.session.add(apc_situation_pro)
|
|
# db.session.commit()
|
|
#
|
|
# ### ApcComposanteEssentielle ###
|
|
# apc_composante_essentielle_id = 1
|
|
# apc_composante_essentielle_competence_id = 1
|
|
# apc_composante_essentielle_libelle = ""
|
|
#
|
|
# apc_composante_essentielle = ApcComposanteEssentielle(
|
|
# apc_composante_essentielle_id,
|
|
# apc_composante_essentielle_competence_id,
|
|
# apc_composante_essentielle_libelle,
|
|
# )
|
|
# db.session.add(apc_composante_essentielle)
|
|
# db.session.commit()
|
|
#
|
|
# ### ApcAppCritique ###
|
|
# apc_app_critique_id = 1
|
|
# apc_app_critique_niveau_id = 1
|
|
# apc_app_critique_code = ""
|
|
# apc_app_critique_libelle = ""
|
|
# apc_app_critique_modules = formation.modules
|
|
#
|
|
# apc_app_critique = ApcAppCritique(
|
|
# apc_app_critique_id,
|
|
# apc_app_critique_niveau_id,
|
|
# apc_app_critique_code,
|
|
# apc_app_critique_libelle,
|
|
# apc_app_critique_modules,
|
|
# )
|
|
# db.session.add(apc_app_critique)
|
|
# db.session.commit()
|
|
#
|
|
# ### ApcNiveau ###
|
|
# apc_niveau_id = 1
|
|
# apc_niveau_competence_id = 1
|
|
# apc_niveau_libelle = ""
|
|
# apc_niveau_annee = ""
|
|
# apc_niveau_ordre = 1
|
|
# apc_niveau_app_critiques = apc_app_critique
|
|
#
|
|
# apc_niveau = ApcNiveau(
|
|
# apc_niveau_id,
|
|
# apc_niveau_competence_id,
|
|
# apc_niveau_libelle,
|
|
# apc_niveau_annee,
|
|
# apc_niveau_ordre,
|
|
# apc_niveau_app_critiques,
|
|
# )
|
|
# db.session.add(apc_niveau)
|
|
# db.session.commit()
|
|
#
|
|
# ### ApcCompetence ###
|
|
# apc_competence_id = 1
|
|
# apc_competence_referentiel_id = 1
|
|
# apc_competence_id_orebut = ""
|
|
# apc_competence_titre = ""
|
|
# apc_competence_titre_long = ""
|
|
# apc_competence_couleur = ""
|
|
# apc_competence_numero = 1
|
|
# apc_competence_xml_attribs = { # xml_attrib : attribute
|
|
# "id": "id_orebut",
|
|
# "nom_court": "titre", # was name
|
|
# "libelle_long": "titre_long",
|
|
# }
|
|
# apc_competence_situations = apc_situation_pro
|
|
# apc_competence_composantes_essentielles = apc_composante_essentielle
|
|
# apc_competence_niveaux = apc_niveau
|
|
#
|
|
# apc_competence = ApcCompetence(
|
|
# apc_competence_id,
|
|
# apc_competence_referentiel_id,
|
|
# apc_competence_id_orebut,
|
|
# apc_competence_titre,
|
|
# apc_competence_titre_long,
|
|
# apc_competence_couleur,
|
|
# apc_competence_numero,
|
|
# apc_competence_xml_attribs,
|
|
# apc_competence_situations,
|
|
# apc_competence_composantes_essentielles,
|
|
# apc_competence_niveaux,
|
|
# )
|
|
# db.session.add(apc_competence)
|
|
# db.session.commit()
|
|
#
|
|
# ### ApcAnneeParcours ###
|
|
# apc_annee_parcours_id = 1
|
|
# apc_annee_parcours_parcours_id = 1
|
|
# apc_annee_parcours_ordre = 1
|
|
#
|
|
# ap_annee_parcours = ApcAnneeParcours(
|
|
# apc_annee_parcours_id, apc_annee_parcours_parcours_id, apc_annee_parcours_ordre
|
|
# )
|
|
#
|
|
# ### ApcParcours ###
|
|
# apc_parcours_id = 1
|
|
# apc_parcours_referentiel_id = 1
|
|
# apc_parcours_numero = 1
|
|
# apc_parcours_code = ""
|
|
# apc_parcours_libelle = ""
|
|
# apc_parcours_annees = ap_annee_parcours
|
|
#
|
|
# apc_parcours = ApcParcours(
|
|
# apc_parcours_id,
|
|
# apc_parcours_referentiel_id,
|
|
# apc_parcours_numero,
|
|
# apc_parcours_code,
|
|
# apc_parcours_libelle,
|
|
# apc_parcours_annees,
|
|
# )
|
|
# db.session.add(apc_parcours)
|
|
# db.session.commit()
|
|
|
|
### ApcReferentielCompetences ###
|
|
apc_referentiel_competences_id = 1
|
|
apc_referentiel_competences_dept_id = 1
|
|
apc_referentiel_competences_annexe = ""
|
|
apc_referentiel_competences_specialite = ""
|
|
apc_referentiel_competences_specialite_long = ""
|
|
apc_referentiel_competences_type_titre = ""
|
|
apc_referentiel_competences_type_structure = ""
|
|
apc_referentiel_competences_type_departement = ""
|
|
apc_referentiel_competences_version_orebut = ""
|
|
apc_referentiel_competences_xml_attribs = {
|
|
"type": "type_titre",
|
|
"version": "version_orebut",
|
|
}
|
|
apc_referentiel_competences_scodoc_date_loaded = ""
|
|
apc_referentiel_competences_scodoc_orig_filename = ""
|
|
# apc_referentiel_competences_competences = apc_competence
|
|
# apc_referentiel_competences_parcours = apc_parcours
|
|
# apc_referentiel_competences_formations = formation
|
|
|
|
apc_referentiel_competences = ApcReferentielCompetences(
|
|
apc_referentiel_competences_id,
|
|
apc_referentiel_competences_dept_id,
|
|
apc_referentiel_competences_annexe,
|
|
apc_referentiel_competences_specialite,
|
|
apc_referentiel_competences_specialite_long,
|
|
apc_referentiel_competences_type_titre,
|
|
apc_referentiel_competences_type_structure,
|
|
apc_referentiel_competences_type_departement,
|
|
apc_referentiel_competences_version_orebut,
|
|
apc_referentiel_competences_xml_attribs,
|
|
# apc_referentiel_competences_scodoc_date_loaded,
|
|
apc_referentiel_competences_scodoc_orig_filename,
|
|
# apc_referentiel_competences_competences,
|
|
# apc_referentiel_competences_parcours,
|
|
# apc_referentiel_competences_formations,
|
|
)
|
|
db.session.add(apc_referentiel_competences)
|
|
db.session.commit()
|
|
|
|
formation.referentiel_competence_id = apc_referentiel_competences.id
|
|
db.session.commit()
|
|
|
|
|
|
def add_absences(formsemestre: FormSemestre):
|
|
"""
|
|
Ajoute des absences en base
|
|
"""
|
|
date_debut = formsemestre.date_debut
|
|
date_fin = formsemestre.date_fin
|
|
|
|
etuds = formsemestre.etuds
|
|
id_db = 1
|
|
for etu in etuds:
|
|
aleatoire = random.randint(0, 1)
|
|
if aleatoire == 1:
|
|
nb_absences = random.randint(1, 5)
|
|
for absence in range(0, nb_absences):
|
|
id = id_db
|
|
etudid = etu.id
|
|
jour = date_debut + random.random() * (date_fin - date_debut)
|
|
estabs = True
|
|
estjust = True if random.randint(0, 1) == 1 else False
|
|
matin = True if random.randint(0, 1) == 1 else False
|
|
description = ""
|
|
abs = Absence(id, etudid, jour, estabs, estjust, matin, description)
|
|
db.session.add(abs)
|
|
db.session.commit()
|
|
id_db += 1
|
|
|
|
|
|
def create_etape_apo(formsemestre: FormSemestre):
|
|
"""
|
|
Ajoute étape apoge au formsemestre
|
|
"""
|
|
etape_apo1 = FormSemestreEtape(
|
|
id=1, formsemestre_id=formsemestre.id, etape_apo="A1"
|
|
)
|
|
db.session.add(etape_apo1)
|
|
|
|
etape_apo2 = FormSemestreEtape(
|
|
id=2, formsemestre_id=formsemestre.id, etape_apo="A2"
|
|
)
|
|
db.session.add(etape_apo2)
|
|
|
|
etape_apo3 = FormSemestreEtape(
|
|
id=3, formsemestre_id=formsemestre.id, etape_apo="A3"
|
|
)
|
|
db.session.add(etape_apo3)
|
|
|
|
list_etapes = [etape_apo1, etape_apo2, etape_apo3]
|
|
formsemestre.etapes = list_etapes
|
|
db.session.commit()
|
|
|
|
|
|
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_notes_evaluations(formsemestre, user_lecteur)
|
|
create_ref_comp(formation)
|
|
add_absences(formsemestre)
|
|
create_etape_apo(formsemestre)
|
|
# à compléter
|
|
# - groupes
|
|
# - absences
|
|
# - notes
|
|
# - décisions de jury
|
|
# ...
|