forked from ScoDoc/ScoDoc
Première version des modèles ScoDoc7 en SQLAlchemy
This commit is contained in:
parent
383fdb0e53
commit
dad6fdd63c
@ -1,7 +0,0 @@
|
|||||||
# -*- coding: UTF-8 -*
|
|
||||||
|
|
||||||
"""ScoDoc8 models
|
|
||||||
"""
|
|
||||||
|
|
||||||
# None, at this point
|
|
||||||
# see auth.models for user/role related models
|
|
57
app/models/__init__.py
Normal file
57
app/models/__init__.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""Modèles base de données ScoDoc
|
||||||
|
XXX version préliminaire ScoDoc8 #sco8 sans département
|
||||||
|
"""
|
||||||
|
|
||||||
|
CODE_STR_LEN = 16 # chaine pour les codes
|
||||||
|
SHORT_STR_LEN = 32 # courtes chaine, eg acronymes
|
||||||
|
APO_CODE_STR_LEN = 16 # nb de car max d'un code Apogée
|
||||||
|
|
||||||
|
from app.models.absences import Absence, AbsenceNotification, BilletAbsence
|
||||||
|
from app.models.entreprises import (
|
||||||
|
Entreprise,
|
||||||
|
EntrepriseCorrespondant,
|
||||||
|
EntrepriseContact,
|
||||||
|
)
|
||||||
|
from app.models.etudiants import (
|
||||||
|
Identite,
|
||||||
|
Adresse,
|
||||||
|
Admission,
|
||||||
|
ItemSuivi,
|
||||||
|
ItemSuiviTag,
|
||||||
|
EtudAnnotation,
|
||||||
|
)
|
||||||
|
from app.models.events import Scolog, ScolarNews
|
||||||
|
from app.models.formations import (
|
||||||
|
NotesFormation,
|
||||||
|
NotesUE,
|
||||||
|
NotesMatiere,
|
||||||
|
NotesModule,
|
||||||
|
NotesTag,
|
||||||
|
)
|
||||||
|
from app.models.formsemestre import (
|
||||||
|
FormSemestre,
|
||||||
|
NotesFormsemestreEtape,
|
||||||
|
FormModalite,
|
||||||
|
NotesFormsemestreUECoef,
|
||||||
|
NotesFormsemestreUEComputationExpr,
|
||||||
|
NotesFormsemestreCustomMenu,
|
||||||
|
NotesFormsemestreInscription,
|
||||||
|
NotesModuleImpl,
|
||||||
|
notes_modules_enseignants,
|
||||||
|
NotesModuleImplInscription,
|
||||||
|
NotesEvaluation,
|
||||||
|
NotesSemSet,
|
||||||
|
notes_semset_formsemestre,
|
||||||
|
)
|
||||||
|
from app.models.groups import Partition, GroupDescr, group_membership
|
||||||
|
from app.models.notes import (
|
||||||
|
ScolarEvent,
|
||||||
|
ScolarFormsemestreValidation,
|
||||||
|
ScolarAutorisationInscription,
|
||||||
|
NotesAppreciations,
|
||||||
|
NotesNotes,
|
||||||
|
NotesNotesLog,
|
||||||
|
)
|
||||||
|
from app.models.preferences import ScoPreferences
|
75
app/models/absences.py
Normal file
75
app/models/absences.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""Gestion des absences
|
||||||
|
"""
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import APO_CODE_STR_LEN
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
|
from app.models import CODE_STR_LEN
|
||||||
|
|
||||||
|
|
||||||
|
class Absence(db.Model):
|
||||||
|
"""une absence (sur une demi-journée)"""
|
||||||
|
|
||||||
|
__tablename__ = "absences"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
etudid = db.Column(db.Integer, db.ForeignKey("identite.id"), index=True)
|
||||||
|
jour = db.Column(db.Date)
|
||||||
|
estabs = db.Column(db.Boolean())
|
||||||
|
estjust = db.Column(db.Boolean())
|
||||||
|
matin = db.Column(db.Boolean())
|
||||||
|
# motif de l'absence:
|
||||||
|
description = db.Column(db.Text())
|
||||||
|
entry_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
# moduleimpid concerne (optionnel):
|
||||||
|
moduleimpl_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_moduleimpl.id"),
|
||||||
|
)
|
||||||
|
# XXX TODO: contrainte ajoutée: vérifier suppression du module
|
||||||
|
# (mettre à NULL sans supprimer)
|
||||||
|
|
||||||
|
|
||||||
|
class AbsenceNotification(db.Model):
|
||||||
|
"""Notification d'absence émise"""
|
||||||
|
|
||||||
|
__tablename__ = "absences_notifications"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
notification_date = db.Column(
|
||||||
|
db.DateTime(timezone=True), server_default=db.func.now()
|
||||||
|
)
|
||||||
|
email = db.Column(db.Text())
|
||||||
|
nbabs = db.Column(db.Integer)
|
||||||
|
nbabsjust = db.Column(db.Integer)
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BilletAbsence(db.Model):
|
||||||
|
"""Billet d'absence (signalement par l'étudiant)"""
|
||||||
|
|
||||||
|
__tablename__ = "billet_absence"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
abs_begin = db.Column(db.DateTime(timezone=True))
|
||||||
|
abs_end = db.Column(db.DateTime(timezone=True))
|
||||||
|
# raison de l'absence:
|
||||||
|
description = db.Column(db.Text())
|
||||||
|
# False: new, True: processed
|
||||||
|
etat = db.Column(db.Boolean(), default=False)
|
||||||
|
entry_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
# true si l'absence _pourrait_ etre justifiée
|
||||||
|
justified = db.Column(db.Boolean(), default=False)
|
69
app/models/entreprises.py
Normal file
69
app/models/entreprises.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""Gestion des absences
|
||||||
|
"""
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import APO_CODE_STR_LEN
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
|
from app.models import CODE_STR_LEN
|
||||||
|
|
||||||
|
|
||||||
|
class Entreprise(db.Model):
|
||||||
|
"""une entreprise"""
|
||||||
|
|
||||||
|
__tablename__ = "entreprises"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
entreprise_id = db.synonym("id")
|
||||||
|
|
||||||
|
nom = db.Column(db.Text)
|
||||||
|
adresse = db.Column(db.Text)
|
||||||
|
ville = db.Column(db.Text)
|
||||||
|
codepostal = db.Column(db.Text)
|
||||||
|
pays = db.Column(db.Text)
|
||||||
|
contact_origine = db.Column(db.Text)
|
||||||
|
secteur = db.Column(db.Text)
|
||||||
|
note = db.Column(db.Text)
|
||||||
|
privee = db.Column(db.Text)
|
||||||
|
localisation = db.Column(db.Text)
|
||||||
|
# -1 inconnue, 0, 25, 50, 75, 100:
|
||||||
|
qualite_relation = db.Column(db.Integer)
|
||||||
|
plus10salaries = db.Column(db.Boolean())
|
||||||
|
date_creation = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
|
||||||
|
|
||||||
|
class EntrepriseCorrespondant(db.Model):
|
||||||
|
"""Personne contact en entreprise"""
|
||||||
|
|
||||||
|
__tablename__ = "entreprise_correspondant"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
entreprise_corresp_id = db.synonym("id")
|
||||||
|
entreprise_id = db.Column(db.Integer, db.ForeignKey("entreprises.id"))
|
||||||
|
nom = db.Column(db.Text)
|
||||||
|
prenom = db.Column(db.Text)
|
||||||
|
civilite = db.Column(db.Text)
|
||||||
|
fonction = db.Column(db.Text)
|
||||||
|
phone1 = db.Column(db.Text)
|
||||||
|
phone2 = db.Column(db.Text)
|
||||||
|
mobile = db.Column(db.Text)
|
||||||
|
mail1 = db.Column(db.Text)
|
||||||
|
mail2 = db.Column(db.Text)
|
||||||
|
fax = db.Column(db.Text)
|
||||||
|
note = db.Column(db.Text)
|
||||||
|
|
||||||
|
|
||||||
|
class EntrepriseContact(db.Model):
|
||||||
|
"""Evènement (contact) avec une entreprise"""
|
||||||
|
|
||||||
|
__tablename__ = "entreprise_contact"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
entreprise_contact_id = db.synonym("id")
|
||||||
|
date = db.Column(db.DateTime(timezone=True))
|
||||||
|
type_contact = db.Column(db.Text)
|
||||||
|
entreprise_id = db.Column(db.Integer, db.ForeignKey("entreprises.id"))
|
||||||
|
entreprise_corresp_id = db.Column(
|
||||||
|
db.Integer, db.ForeignKey("entreprise_correspondant.id")
|
||||||
|
)
|
||||||
|
etudid = db.Column(db.Integer) # sans contrainte pour garder logs après suppression
|
||||||
|
description = db.Column(db.Text)
|
||||||
|
enseignant = db.Column(db.Text)
|
153
app/models/etudiants.py
Normal file
153
app/models/etudiants.py
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""Définition d'un étudiant
|
||||||
|
et données rattachées (adresses, annotations, ...)
|
||||||
|
"""
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import APO_CODE_STR_LEN
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
|
from app.models import CODE_STR_LEN
|
||||||
|
|
||||||
|
|
||||||
|
class Identite(db.Model):
|
||||||
|
"""étudiant"""
|
||||||
|
|
||||||
|
__tablename__ = "identite"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
etudid = db.synonym("id")
|
||||||
|
|
||||||
|
nom = db.Column(db.Text())
|
||||||
|
prenom = db.Column(db.Text())
|
||||||
|
nom_usuel = db.Column(db.Text())
|
||||||
|
# optionnel (si present, affiché à la place du nom)
|
||||||
|
civilite = db.Column(db.String(1), nullable=False)
|
||||||
|
__table_args__ = (db.CheckConstraint("civilite IN ('M', 'F', 'X')"),)
|
||||||
|
|
||||||
|
date_naissance = db.Column(db.Date)
|
||||||
|
lieu_naissance = db.Column(db.Text())
|
||||||
|
dept_naissance = db.Column(db.Text())
|
||||||
|
nationalite = db.Column(db.Text())
|
||||||
|
statut = db.Column(db.Text())
|
||||||
|
boursier = db.Column(db.Boolean()) # True si boursier ('O' en ScoDoc7)
|
||||||
|
photo_filename = db.Column(db.Text())
|
||||||
|
code_nip = db.Column(db.String(CODE_STR_LEN), unique=True)
|
||||||
|
code_ine = db.Column(db.String(CODE_STR_LEN), unique=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Adresse(db.Model):
|
||||||
|
"""Adresse d'un étudiant
|
||||||
|
(le modèle permet plusieurs adresses, mais l'UI n'en gère qu'une seule)
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "adresse"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
adresse_id = db.synonym("id")
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
email = db.Column(db.Text()) # mail institutionnel
|
||||||
|
emailperso = db.Column(db.Text) # email personnel (exterieur)
|
||||||
|
domicile = db.Column(db.Text)
|
||||||
|
codepostaldomicile = db.Column(db.Text)
|
||||||
|
villedomicile = db.Column(db.Text)
|
||||||
|
paysdomicile = db.Column(db.Text)
|
||||||
|
telephone = db.Column(db.Text)
|
||||||
|
telephonemobile = db.Column(db.Text)
|
||||||
|
fax = db.Column(db.Text)
|
||||||
|
typeadresse = db.Column(db.Text, default="domicile", nullable=False)
|
||||||
|
description = db.Column(db.Text)
|
||||||
|
|
||||||
|
|
||||||
|
class Admission(db.Model):
|
||||||
|
"""Informations liées à l'admission d'un étudiant"""
|
||||||
|
|
||||||
|
__tablename__ = "admissions"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
adm_id = db.synonym("id")
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
# Anciens champs de ScoDoc7, à revoir pour être plus générique et souple
|
||||||
|
# notamment dans le cadre du bac 2021
|
||||||
|
# de plus, certaines informations liées à APB ne sont plus disponibles
|
||||||
|
# avec Parcoursup
|
||||||
|
annee = db.Column(db.Integer)
|
||||||
|
bac = db.Column(db.Text)
|
||||||
|
specialite = db.Column(db.Text)
|
||||||
|
annee_bac = db.Column(db.Integer)
|
||||||
|
math = db.Column(db.Text)
|
||||||
|
physique = db.Column(db.Float)
|
||||||
|
anglais = db.Column(db.Float)
|
||||||
|
francais = db.Column(db.Float)
|
||||||
|
# Rang dans les voeux du candidat (inconnu avec APB et PS)
|
||||||
|
rang = db.Column(db.Integer)
|
||||||
|
# Qualité et décision du jury d'admission (ou de l'examinateur)
|
||||||
|
qualite = db.Column(db.Float)
|
||||||
|
rapporteur = db.Column(db.Text)
|
||||||
|
decision = db.Column(db.Text)
|
||||||
|
score = db.Column(db.Float)
|
||||||
|
commentaire = db.Column(db.Text)
|
||||||
|
# Lycée d'origine:
|
||||||
|
nomlycee = db.Column(db.Text)
|
||||||
|
villelycee = db.Column(db.Text)
|
||||||
|
codepostallycee = db.Column(db.Text)
|
||||||
|
codelycee = db.Column(db.Text)
|
||||||
|
# 'APB', 'APC-PC', 'CEF', 'Direct', '?' (autre)
|
||||||
|
type_admission = db.Column(db.Text)
|
||||||
|
# était boursier dans le cycle precedent (lycee) ?
|
||||||
|
boursier_prec = db.Column(db.Boolean())
|
||||||
|
# classement par le jury d'admission (1 à N),
|
||||||
|
# global (pas celui d'APB si il y a des groupes)
|
||||||
|
classement = db.Column(db.Integer)
|
||||||
|
# code du groupe APB
|
||||||
|
apb_groupe = db.Column(db.Text)
|
||||||
|
# classement (1..Ngr) par le jury dans le groupe APB
|
||||||
|
apb_classement_gr = db.Column(db.Integer)
|
||||||
|
|
||||||
|
|
||||||
|
# Suivi scolarité / débouchés
|
||||||
|
class ItemSuivi(db.Model):
|
||||||
|
__tablename__ = "itemsuivi"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
itemsuivi_id = db.synonym("id")
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
item_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
situation = db.Column(db.Text)
|
||||||
|
|
||||||
|
|
||||||
|
class ItemSuiviTag(db.Model):
|
||||||
|
__tablename__ = "itemsuivi_tags"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
tag_id = db.synonym("id")
|
||||||
|
title = db.Column(db.String(SHORT_STR_LEN), nullable=False, unique=True)
|
||||||
|
|
||||||
|
|
||||||
|
# Association tag <-> module
|
||||||
|
itemsuivi_tags_assoc = db.Table(
|
||||||
|
"itemsuivi_tags_assoc",
|
||||||
|
db.Column("tag_id", db.Integer, db.ForeignKey("itemsuivi_tags.id")),
|
||||||
|
db.Column("itemsuivi_id", db.Integer, db.ForeignKey("itemsuivi.id")),
|
||||||
|
)
|
||||||
|
# ON DELETE CASCADE ?
|
||||||
|
|
||||||
|
|
||||||
|
class EtudAnnotation(db.Model):
|
||||||
|
"""Annotation sur un étudiant"""
|
||||||
|
|
||||||
|
__tablename__ = "etud_annotations"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
etudid = db.Column(db.Integer) # sans contrainte pour garder logs après suppression
|
||||||
|
authenticated_user = db.Column(db.Text)
|
||||||
|
comment = db.Column(db.Text)
|
35
app/models/events.py
Normal file
35
app/models/events.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""Evenements et logs divers
|
||||||
|
"""
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import APO_CODE_STR_LEN
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
|
from app.models import CODE_STR_LEN
|
||||||
|
|
||||||
|
|
||||||
|
class Scolog(db.Model):
|
||||||
|
"""Log des actions (journal modif etudiants)"""
|
||||||
|
|
||||||
|
__tablename__ = "scolog"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
etudid = db.Column(db.Integer) # sans contrainte pour garder logs après suppression
|
||||||
|
authenticated_user = db.Column(db.Text) # login, sans contrainte
|
||||||
|
# zope_remote_addr suppressed
|
||||||
|
|
||||||
|
|
||||||
|
class ScolarNews(db.Model):
|
||||||
|
"""Nouvelles pour page d'accueil"""
|
||||||
|
|
||||||
|
__tablename__ = "scolar_news"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
authenticated_user = db.Column(db.Text) # login, sans contrainte
|
||||||
|
# type in 'INSCR', 'NOTES', 'FORM', 'SEM', 'MISC'
|
||||||
|
type = db.Column(db.String(SHORT_STR_LEN))
|
||||||
|
object = db.Column(db.Integer) # moduleimpl_id, formation_id, formsemestre_id
|
||||||
|
text = db.Column(db.Text)
|
||||||
|
url = db.Column(db.Text)
|
117
app/models/formations.py
Normal file
117
app/models/formations.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
"""ScoDoc8 models : Formations (hors BUT)
|
||||||
|
"""
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import APO_CODE_STR_LEN
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
|
|
||||||
|
|
||||||
|
class NotesFormation(db.Model):
|
||||||
|
"""Programme pédagogique d'une formation"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_formations"
|
||||||
|
__table_args__ = (db.UniqueConstraint("acronyme", "titre", "version"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
formation_id = db.synonym("id")
|
||||||
|
acronyme = db.Column(db.String(SHORT_STR_LEN), nullable=False)
|
||||||
|
titre = db.Column(db.Text(), nullable=False)
|
||||||
|
version = db.Column(db.Integer, default=1)
|
||||||
|
formation_code = db.Column(db.String(SHORT_STR_LEN), nullable=False)
|
||||||
|
type_parcours = db.Column(db.Integer, default=0)
|
||||||
|
code_specialite = db.Column(db.String(SHORT_STR_LEN))
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(NotesFormation, self).__init__(**kwargs)
|
||||||
|
if self.formation_code is None:
|
||||||
|
# génère formation_code à la création
|
||||||
|
self.formation_code = f"FCOD{self.id:03d}"
|
||||||
|
|
||||||
|
|
||||||
|
class NotesUE(db.Model):
|
||||||
|
"""Unité d'Enseignement"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_ue"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
ue_id = db.synonym("id")
|
||||||
|
formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id"))
|
||||||
|
acronyme = db.Column(db.String(SHORT_STR_LEN), nullable=False)
|
||||||
|
numero = db.Column(db.Integer) # ordre de présentation
|
||||||
|
titre = db.Column(db.Text())
|
||||||
|
# Type d'UE: 0 normal ("fondamentale"), 1 "sport", 2 "projet et stage (LP)",
|
||||||
|
# 4 "élective"
|
||||||
|
type = db.Column(db.Integer, default=0)
|
||||||
|
ue_code = db.Column(db.String(SHORT_STR_LEN), nullable=False)
|
||||||
|
ects = db.Column(db.Float) # nombre de credits ECTS
|
||||||
|
is_external = db.Column(db.Boolean(), nullable=False, default=False)
|
||||||
|
# id de l'element pedagogique Apogee correspondant:
|
||||||
|
code_apogee = db.Column(db.String(APO_CODE_STR_LEN))
|
||||||
|
# coef UE, utilise seulement si l'option use_ue_coefs est activée:
|
||||||
|
coefficient = db.Column(db.Float)
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(NotesUE, self).__init__(**kwargs)
|
||||||
|
if self.ue_code is None:
|
||||||
|
# génère code à la création
|
||||||
|
self.ue_code = f"UCOD{self.ue_id:03d}"
|
||||||
|
|
||||||
|
|
||||||
|
class NotesMatiere(db.Model):
|
||||||
|
"""Matières: regroupe les modules d'une UE
|
||||||
|
La matière a peu d'utilité en dehors de la présentation des modules
|
||||||
|
d'une UE.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_matieres"
|
||||||
|
__table_args__ = (db.UniqueConstraint("ue_id", "titre"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
matiere_id = db.synonym("id")
|
||||||
|
ue_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"))
|
||||||
|
titre = db.Column(db.Text())
|
||||||
|
numero = db.Column(db.Integer) # ordre de présentation
|
||||||
|
|
||||||
|
|
||||||
|
class NotesModule(db.Model):
|
||||||
|
"""Module"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_modules"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
module_id = db.synonym("id")
|
||||||
|
titre = db.Column(db.Text())
|
||||||
|
abbrev = db.Column(db.Text()) # nom court
|
||||||
|
code = db.Column(db.String(SHORT_STR_LEN), nullable=False)
|
||||||
|
heures_cours = db.Column(db.Float)
|
||||||
|
heures_td = db.Column(db.Float)
|
||||||
|
heures_tp = db.Column(db.Float)
|
||||||
|
coefficient = db.Column(db.Float) # coef PPN
|
||||||
|
ue_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"))
|
||||||
|
formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id"))
|
||||||
|
matiere_id = db.Column(db.Integer, db.ForeignKey("notes_matieres.id"))
|
||||||
|
# pas un id mais le numéro du semestre: 1, 2, ...
|
||||||
|
semestre_id = db.Column(db.Integer, nullable=False, default=1)
|
||||||
|
numero = db.Column(db.Integer) # ordre de présentation
|
||||||
|
# id de l'element pedagogique Apogee correspondant:
|
||||||
|
code_apogee = db.Column(db.String(APO_CODE_STR_LEN))
|
||||||
|
module_type = db.Column(db.Integer) # NULL ou 0:defaut, 1: malus (NOTES_MALUS)
|
||||||
|
|
||||||
|
|
||||||
|
class NotesTag(db.Model):
|
||||||
|
"""Tag sur un module"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_tags"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
tag_id = db.synonym("id")
|
||||||
|
title = db.Column(db.String(SHORT_STR_LEN), nullable=False, unique=True)
|
||||||
|
|
||||||
|
|
||||||
|
# Association tag <-> module
|
||||||
|
notes_modules_tags = db.Table(
|
||||||
|
"notes_modules_tags",
|
||||||
|
db.Column("tag_id", db.Integer, db.ForeignKey("notes_tags.id")),
|
||||||
|
db.Column("module_id", db.Integer, db.ForeignKey("notes_modules.id")),
|
||||||
|
)
|
284
app/models/formsemestre.py
Normal file
284
app/models/formsemestre.py
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""ScoDoc8 models
|
||||||
|
"""
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import APO_CODE_STR_LEN
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
|
from app.models import CODE_STR_LEN
|
||||||
|
|
||||||
|
|
||||||
|
class FormSemestre(db.Model):
|
||||||
|
"""Mise en oeuvre d'un semestre de formation
|
||||||
|
was notes_formsemestre
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_formsemestre"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
formsemestre_id = db.synonym("id")
|
||||||
|
formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id"))
|
||||||
|
semestre_id = db.Column(db.Integer, nullable=False, default=1)
|
||||||
|
titre = db.Column(db.Text())
|
||||||
|
date_debut = db.Column(db.Date())
|
||||||
|
date_fin = db.Column(db.Date())
|
||||||
|
etat = db.Column(db.Boolean(), nullable=False, default=True) # False si verrouillé
|
||||||
|
modalite = db.Column(db.String(16), db.ForeignKey("form_modalite.modalite"))
|
||||||
|
# gestion compensation sem DUT:
|
||||||
|
gestion_compensation = db.Column(db.Boolean(), nullable=False, default=False)
|
||||||
|
# ne publie pas le bulletin XML:
|
||||||
|
bul_hide_xml = db.Column(db.Boolean(), nullable=False, default=False)
|
||||||
|
# semestres decales (pour gestion jurys):
|
||||||
|
gestion_semestrielle = db.Column(db.Boolean(), nullable=False, default=False)
|
||||||
|
# couleur fond bulletins HTML:
|
||||||
|
bul_bgcolor = db.Column(db.String(SHORT_STR_LEN), default="white")
|
||||||
|
# autorise resp. a modifier semestre:
|
||||||
|
resp_can_edit = db.Column(db.Boolean(), nullable=False, default=False)
|
||||||
|
# autorise resp. a modifier slt les enseignants:
|
||||||
|
resp_can_change_ens = db.Column(db.Boolean(), nullable=False, default=True)
|
||||||
|
# autorise les ens a creer des evals:
|
||||||
|
ens_can_edit_eval = db.Column(db.Boolean(), nullable=False, default=False)
|
||||||
|
# code element semestre Apogee, eg VRTW1 ou V2INCS4,V2INLS4
|
||||||
|
elt_sem_apo = db.Column(db.String(APO_CODE_STR_LEN))
|
||||||
|
# code element annee Apogee, eg VRT1A ou V2INLA,V2INCA
|
||||||
|
elt_annee_apo = db.Column(db.String(APO_CODE_STR_LEN))
|
||||||
|
|
||||||
|
etapes = db.relationship(
|
||||||
|
"NotesFormsemestreEtape", cascade="all,delete", backref="notes_formsemestre"
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(FormSemestre, self).__init__(**kwargs)
|
||||||
|
if self.modalite is None:
|
||||||
|
self.modalite = FormModalite.DEFAULT_MODALITE
|
||||||
|
|
||||||
|
|
||||||
|
# Association id des utilisateurs responsables (aka directeurs des etudes) du semestre
|
||||||
|
notes_formsemestre_responsables = db.Table(
|
||||||
|
"notes_formsemestre_responsables",
|
||||||
|
db.Column(
|
||||||
|
"formsemestre_id",
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
),
|
||||||
|
db.Column("responsable_id", db.Integer, db.ForeignKey("user.id")),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NotesFormsemestreEtape(db.Model):
|
||||||
|
"""Étape Apogée associées au semestre"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_formsemestre_etapes"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
etape_apo = db.Column(db.String(APO_CODE_STR_LEN))
|
||||||
|
|
||||||
|
|
||||||
|
class FormModalite(db.Model):
|
||||||
|
"""Modalités de formation, utilisées pour la présentation
|
||||||
|
(grouper les semestres, générer des codes, etc.)
|
||||||
|
"""
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
modalite = db.Column(db.String(16), unique=True, index=True) # code
|
||||||
|
titre = db.Column(db.Text()) # texte explicatif
|
||||||
|
# numero = ordre de presentation)
|
||||||
|
numero = db.Column(db.Integer)
|
||||||
|
|
||||||
|
DEFAULT_MODALITE = "FI"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def insert_modalites():
|
||||||
|
"""Create default modalities"""
|
||||||
|
numero = 0
|
||||||
|
for (code, titre) in (
|
||||||
|
(FormModalite.DEFAULT_MODALITE, "Formation Initiale"),
|
||||||
|
("FAP", "Apprentissage"),
|
||||||
|
("FC", "Formation Continue"),
|
||||||
|
("DEC", "Formation Décalées"),
|
||||||
|
("LIC", "Licence"),
|
||||||
|
("CPRO", "Contrats de Professionnalisation"),
|
||||||
|
("DIST", "À distance"),
|
||||||
|
("ETR", "À l'étranger"),
|
||||||
|
("EXT", "Extérieur"),
|
||||||
|
("OTHER", "Autres formations"),
|
||||||
|
):
|
||||||
|
modalite = FormModalite.query.filter_by(modalite=code).first()
|
||||||
|
if modalite is None:
|
||||||
|
modalite = FormModalite(modalite=code, titre=titre, numero=numero)
|
||||||
|
db.session.add(modalite)
|
||||||
|
numero += 1
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
|
class NotesFormsemestreUECoef(db.Model):
|
||||||
|
"""Coef des UE capitalisees arrivant dans ce semestre"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_formsemestre_uecoef"
|
||||||
|
__table_args__ = (db.UniqueConstraint("formsemestre_id", "ue_id"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
formsemestre_uecoef_id = db.synonym("id")
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
ue_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_ue.id"),
|
||||||
|
)
|
||||||
|
coefficient = db.Column(db.Float, nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
class NotesFormsemestreUEComputationExpr(db.Model):
|
||||||
|
"""Formules utilisateurs pour calcul moyenne UE"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_formsemestre_ue_computation_expr"
|
||||||
|
__table_args__ = (db.UniqueConstraint("formsemestre_id", "ue_id"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
notes_formsemestre_ue_computation_expr_id = db.synonym("id")
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
ue_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_ue.id"),
|
||||||
|
)
|
||||||
|
# formule de calcul moyenne
|
||||||
|
computation_expr = db.Column(db.Text())
|
||||||
|
|
||||||
|
|
||||||
|
class NotesFormsemestreCustomMenu(db.Model):
|
||||||
|
"""Menu custom associe au semestre"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_formsemestre_custommenu"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
custommenu_id = db.synonym("id")
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
title = db.Column(db.Text())
|
||||||
|
url = db.Column(db.Text())
|
||||||
|
idx = db.Column(db.Integer, default=0) # rang dans le menu
|
||||||
|
|
||||||
|
|
||||||
|
class NotesFormsemestreInscription(db.Model):
|
||||||
|
"""Inscription à un semestre de formation"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_formsemestre_inscription"
|
||||||
|
__table_args__ = (db.UniqueConstraint("formsemestre_id", "etudid"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
formsemestre_inscription_id = db.synonym("id")
|
||||||
|
|
||||||
|
etudid = db.Column(db.Integer, db.ForeignKey("identite.id"))
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
# I inscrit, D demission en cours de semestre, DEF si "defaillant"
|
||||||
|
etat = db.Column(db.String(CODE_STR_LEN))
|
||||||
|
# etape apogee d'inscription (experimental 2020)
|
||||||
|
etape = db.Column(db.String(APO_CODE_STR_LEN))
|
||||||
|
|
||||||
|
|
||||||
|
class NotesModuleImpl(db.Model):
|
||||||
|
"""Mise en oeuvre d'un module pour une annee/semestre"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_moduleimpl"
|
||||||
|
__table_args__ = (db.UniqueConstraint("formsemestre_id", "module_id"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
moduleimpl_id = db.synonym("id")
|
||||||
|
module_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_modules.id"),
|
||||||
|
)
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
responsable_id = db.Column("responsable_id", db.Integer, db.ForeignKey("user.id"))
|
||||||
|
# formule de calcul moyenne:
|
||||||
|
computation_expr = db.Column(db.Text())
|
||||||
|
|
||||||
|
|
||||||
|
# Enseignants (chargés de TD ou TP) d'un moduleimpl
|
||||||
|
notes_modules_enseignants = db.Table(
|
||||||
|
"notes_modules_enseignants",
|
||||||
|
db.Column(
|
||||||
|
"moduleimpl_id",
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_moduleimpl.id"),
|
||||||
|
),
|
||||||
|
db.Column("ens_id", db.Integer, db.ForeignKey("user.id")),
|
||||||
|
)
|
||||||
|
# XXX il manque probablement une relation pour gérer cela
|
||||||
|
|
||||||
|
|
||||||
|
class NotesModuleImplInscription(db.Model):
|
||||||
|
"""Inscription à un module (etudiants,moduleimpl)"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_moduleimpl_inscription"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
moduleimpl_inscription_id = db.synonym("id")
|
||||||
|
db.Column(
|
||||||
|
"moduleimpl_id",
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_moduleimpl.moduleimpl_id"),
|
||||||
|
)
|
||||||
|
etudid = db.Column(db.Integer, db.ForeignKey("identite.id"))
|
||||||
|
|
||||||
|
|
||||||
|
class NotesEvaluation(db.Model):
|
||||||
|
"""Evaluation (contrôle, examen, ...)"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_evaluation"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
evaluation_id = db.synonym("id")
|
||||||
|
jour = db.Column(db.Date)
|
||||||
|
heure_debut = db.Column(db.Time)
|
||||||
|
heure_fin = db.Column(db.Time)
|
||||||
|
description = db.Column(db.Text)
|
||||||
|
note_max = db.Column(db.Float)
|
||||||
|
coefficient = db.Column(db.Float)
|
||||||
|
visibulletin = db.Column(db.Boolean, nullable=False, default=True)
|
||||||
|
publish_incomplete = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
# type d'evaluation: False normale, True rattrapage:
|
||||||
|
evaluation_type = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
# ordre de presentation (par défaut, le plus petit numero
|
||||||
|
# est la plus ancienne eval):
|
||||||
|
numero = db.Column(db.Integer)
|
||||||
|
|
||||||
|
|
||||||
|
class NotesSemSet(db.Model):
|
||||||
|
"""semsets: ensemble de formsemestres pour exports Apogée"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_semset"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
semset_id = db.synonym("id")
|
||||||
|
title = db.Column(db.Text)
|
||||||
|
annee_scolaire = db.Column(db.Integer, nullable=True, default=None)
|
||||||
|
# periode: 0 (année), 1 (Simpair), 2 (Spair)
|
||||||
|
sem_id = db.Column(db.Integer, nullable=True, default=None)
|
||||||
|
|
||||||
|
|
||||||
|
# Association:
|
||||||
|
notes_semset_formsemestre = db.Table(
|
||||||
|
"notes_semset_formsemestre",
|
||||||
|
db.Column("formsemestre_id", db.Integer, db.ForeignKey("notes_formsemestre.id")),
|
||||||
|
db.Column("semset_id", db.Integer, db.ForeignKey("notes_semset.id")),
|
||||||
|
db.UniqueConstraint("formsemestre_id", "semset_id"),
|
||||||
|
)
|
60
app/models/groups.py
Normal file
60
app/models/groups.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""Groups & partitions
|
||||||
|
"""
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import APO_CODE_STR_LEN
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
|
from app.models import CODE_STR_LEN
|
||||||
|
|
||||||
|
|
||||||
|
class Partition(db.Model):
|
||||||
|
"""Partition: découpage d'une promotion en groupes"""
|
||||||
|
|
||||||
|
__table_args__ = (db.UniqueConstraint("formsemestre_id", "partition_name"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
partition_id = db.synonym("id")
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
# "TD", "TP", ... (NULL for 'all')
|
||||||
|
partition_name = db.Column(db.String(SHORT_STR_LEN))
|
||||||
|
# numero = ordre de presentation)
|
||||||
|
numero = db.Column(db.Integer)
|
||||||
|
bul_show_rank = db.Column(db.Boolean(), nullable=False, default=False)
|
||||||
|
show_in_lists = db.Column(db.Boolean(), nullable=False, default=True)
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(Partition, self).__init__(**kwargs)
|
||||||
|
if self.numero is None:
|
||||||
|
# génère numero à la création
|
||||||
|
last_partition = Partition.query.order_by(Partition.numero.desc()).first()
|
||||||
|
if last_partition:
|
||||||
|
self.numero = last_partition.numero + 1
|
||||||
|
else:
|
||||||
|
self.numero = 1
|
||||||
|
|
||||||
|
|
||||||
|
class GroupDescr(db.Model):
|
||||||
|
"""Description d'un groupe d'une partition"""
|
||||||
|
|
||||||
|
__tablename__ = "group_descr"
|
||||||
|
__table_args__ = (db.UniqueConstraint("partition_id", "group_name"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
group_id = db.synonym("id")
|
||||||
|
partition_id = db.Column(db.Integer, db.ForeignKey("partition.id"))
|
||||||
|
# "A", "C2", ... (NULL for 'all'):
|
||||||
|
group_name = db.Column(db.String(SHORT_STR_LEN))
|
||||||
|
|
||||||
|
|
||||||
|
group_membership = db.Table(
|
||||||
|
"group_membership",
|
||||||
|
db.Column("etudid", db.Integer, db.ForeignKey("identite.id")),
|
||||||
|
db.Column("group_id", db.Integer, db.ForeignKey("group_descr.id")),
|
||||||
|
db.UniqueConstraint("etudid", "group_id"),
|
||||||
|
)
|
160
app/models/notes.py
Normal file
160
app/models/notes.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""Notes, décisions de jury, évènements scolaires
|
||||||
|
"""
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import APO_CODE_STR_LEN
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
|
from app.models import CODE_STR_LEN
|
||||||
|
|
||||||
|
|
||||||
|
class ScolarEvent(db.Model):
|
||||||
|
"""Evenement dans le parcours scolaire d'un étudiant"""
|
||||||
|
|
||||||
|
__tablename__ = "scolar_events"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
event_id = db.synonym("id")
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
ue_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_ue.id"),
|
||||||
|
)
|
||||||
|
# 'CREATION', 'INSCRIPTION', 'DEMISSION',
|
||||||
|
# 'AUT_RED', 'EXCLUS', 'VALID_UE', 'VALID_SEM'
|
||||||
|
# 'ECHEC_SEM'
|
||||||
|
# 'UTIL_COMPENSATION'
|
||||||
|
event_type = db.Column(db.String(SHORT_STR_LEN))
|
||||||
|
# Semestre compensé par formsemestre_id:
|
||||||
|
comp_formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ScolarFormsemestreValidation(db.Model):
|
||||||
|
"""Décisions de jury"""
|
||||||
|
|
||||||
|
__tablename__ = "scolar_formsemestre_validation"
|
||||||
|
# Assure unicité de la décision:
|
||||||
|
__table_args__ = (db.UniqueConstraint("etudid", "formsemestre_id", "ue_id"),)
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
formsemestre_validation_id = db.synonym("id")
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
ue_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_ue.id"),
|
||||||
|
)
|
||||||
|
code = db.Column(db.String(CODE_STR_LEN), nullable=False)
|
||||||
|
# NULL pour les UE, True|False pour les semestres:
|
||||||
|
assidu = db.Column(db.Boolean)
|
||||||
|
event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
# NULL sauf si compense un semestre:
|
||||||
|
compense_formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
moy_ue = db.Column(db.Float)
|
||||||
|
# (normalement NULL) indice du semestre, utile seulement pour
|
||||||
|
# UE "antérieures" et si la formation définit des UE utilisées
|
||||||
|
# dans plusieurs semestres (cas R&T IUTV v2)
|
||||||
|
semestre_id = db.Column(db.Integer)
|
||||||
|
# Si UE validée dans le cursus d'un autre etablissement
|
||||||
|
is_external = db.Column(db.Boolean, default=False)
|
||||||
|
|
||||||
|
|
||||||
|
class ScolarAutorisationInscription(db.Model):
|
||||||
|
"""Autorisation d'inscription dans un semestre"""
|
||||||
|
|
||||||
|
__tablename__ = "scolar_autorisation_inscription"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
autorisation_inscription_id = db.synonym("id")
|
||||||
|
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
formation_code = db.Column(db.String(CODE_STR_LEN), nullable=False)
|
||||||
|
# semestre ou on peut s'inscrire:
|
||||||
|
semestre_id = db.Column(db.Integer)
|
||||||
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
origin_formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NotesAppreciations(db.Model):
|
||||||
|
"""Appréciations sur bulletins"""
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
formsemestre_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("notes_formsemestre.id"),
|
||||||
|
)
|
||||||
|
author = db.Column(db.Text) # login, sans contrainte
|
||||||
|
comment = db.Column(db.Text) # texte libre
|
||||||
|
|
||||||
|
|
||||||
|
class NotesNotes(db.Model):
|
||||||
|
"""Une note"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_notes"
|
||||||
|
__table_args__ = (db.UniqueConstraint("etudid", "evaluation_id"),)
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
evaluation_id = db.Column(
|
||||||
|
db.Integer, db.ForeignKey("notes_evaluation.id"), index=True
|
||||||
|
)
|
||||||
|
value = db.Column(db.Float)
|
||||||
|
# infos sur saisie de cette note:
|
||||||
|
comment = db.Column(db.Text) # texte libre
|
||||||
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
uid = db.Column(db.Integer, db.ForeignKey("user.id"))
|
||||||
|
|
||||||
|
|
||||||
|
class NotesNotesLog(db.Model):
|
||||||
|
"""Historique des modifs sur notes (anciennes entrees de notes_notes)"""
|
||||||
|
|
||||||
|
__tablename__ = "notes_notes_log"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
|
||||||
|
etudid = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
db.ForeignKey("identite.id"),
|
||||||
|
)
|
||||||
|
evaluation_id = db.Column(
|
||||||
|
db.Integer,
|
||||||
|
# db.ForeignKey("notes_evaluation.id"),
|
||||||
|
index=True,
|
||||||
|
)
|
||||||
|
value = db.Column(db.Float)
|
||||||
|
# infos sur saisie de cette note:
|
||||||
|
comment = db.Column(db.Text) # texte libre
|
||||||
|
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
uid = db.Column(db.Integer, db.ForeignKey("user.id"))
|
18
app/models/preferences.py
Normal file
18
app/models/preferences.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# -*- coding: UTF-8 -*
|
||||||
|
|
||||||
|
"""Model : preferences
|
||||||
|
"""
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
|
||||||
|
|
||||||
|
class ScoPreferences(db.Model):
|
||||||
|
"""ScoDoc preferences"""
|
||||||
|
|
||||||
|
__tablename__ = "sco_prefs"
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
pref_id = db.synonym("id")
|
||||||
|
dept = db.Column(db.String(16), index=True)
|
||||||
|
name = db.Column(db.String(128), nullable=False)
|
||||||
|
value = db.Column(db.Text())
|
||||||
|
formsemestre_id = db.Column(db.Integer, db.ForeignKey("notes_formsemestre.id"))
|
@ -102,7 +102,7 @@ def do_modalite_delete(context, oid, REQUEST=None):
|
|||||||
_modaliteEditor.delete(cnx, oid)
|
_modaliteEditor.delete(cnx, oid)
|
||||||
|
|
||||||
|
|
||||||
def do_modalite_edit(context, *args, **kw):
|
def do_modalite_edit(context, *args, **kw): # unused
|
||||||
"edit a modalite"
|
"edit a modalite"
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
# check
|
# check
|
||||||
|
@ -202,34 +202,34 @@ CREATE TABLE etud_annotations (
|
|||||||
) WITH OIDS;
|
) WITH OIDS;
|
||||||
|
|
||||||
-- ------------ Nouvelle gestion des absences ------------
|
-- ------------ Nouvelle gestion des absences ------------
|
||||||
CREATE SEQUENCE abs_idgen;
|
-- CREATE SEQUENCE abs_idgen;
|
||||||
CREATE FUNCTION abs_newid( text ) returns text as '
|
-- CREATE FUNCTION abs_newid( text ) returns text as '
|
||||||
select $1 || to_char( nextval(''abs_idgen''), ''FM999999999'' )
|
-- select $1 || to_char( nextval(''abs_idgen''), ''FM999999999'' )
|
||||||
as result;
|
-- as result;
|
||||||
' language SQL;
|
-- ' language SQL;
|
||||||
|
|
||||||
CREATE TABLE abs_absences (
|
-- CREATE TABLE abs_absences (
|
||||||
absid text default abs_newid('AB') PRIMARY KEY,
|
-- absid text default abs_newid('AB') PRIMARY KEY,
|
||||||
etudid character(32),
|
-- etudid character(32),
|
||||||
abs_begin timestamp with time zone,
|
-- abs_begin timestamp with time zone,
|
||||||
abs_end timestamp with time zone
|
-- abs_end timestamp with time zone
|
||||||
) WITH OIDS;
|
-- ) WITH OIDS;
|
||||||
|
|
||||||
CREATE TABLE abs_presences (
|
-- CREATE TABLE abs_presences (
|
||||||
absid text default abs_newid('PR') PRIMARY KEY,
|
-- absid text default abs_newid('PR') PRIMARY KEY,
|
||||||
etudid character(32),
|
-- etudid character(32),
|
||||||
abs_begin timestamp with time zone,
|
-- abs_begin timestamp with time zone,
|
||||||
abs_end timestamp with time zone
|
-- abs_end timestamp with time zone
|
||||||
) WITH OIDS;
|
-- ) WITH OIDS;
|
||||||
|
|
||||||
CREATE TABLE abs_justifs (
|
-- CREATE TABLE abs_justifs (
|
||||||
absid text default abs_newid('JU') PRIMARY KEY,
|
-- absid text default abs_newid('JU') PRIMARY KEY,
|
||||||
etudid character(32),
|
-- etudid character(32),
|
||||||
abs_begin timestamp with time zone,
|
-- abs_begin timestamp with time zone,
|
||||||
abs_end timestamp with time zone,
|
-- abs_end timestamp with time zone,
|
||||||
category text,
|
-- category text,
|
||||||
description text
|
-- description text
|
||||||
) WITH OIDS;
|
-- ) WITH OIDS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -600,12 +600,12 @@ CREATE TABLE scolar_events (
|
|||||||
etudid text,
|
etudid text,
|
||||||
event_date timestamp default now(),
|
event_date timestamp default now(),
|
||||||
formsemestre_id text REFERENCES notes_formsemestre(formsemestre_id),
|
formsemestre_id text REFERENCES notes_formsemestre(formsemestre_id),
|
||||||
ue_id text REFERENCES notes_ue(ue_id),
|
ue_id text REFERENCES notes_ue(ue_id),
|
||||||
event_type text, -- 'CREATION', 'INSCRIPTION', 'DEMISSION',
|
event_type text, -- 'CREATION', 'INSCRIPTION', 'DEMISSION',
|
||||||
-- 'AUT_RED', 'EXCLUS', 'VALID_UE', 'VALID_SEM'
|
-- 'AUT_RED', 'EXCLUS', 'VALID_UE', 'VALID_SEM'
|
||||||
-- 'ECHEC_SEM'
|
-- 'ECHEC_SEM'
|
||||||
-- 'UTIL_COMPENSATION'
|
-- 'UTIL_COMPENSATION'
|
||||||
comp_formsemestre_id text REFERENCES notes_formsemestre(formsemestre_id)
|
comp_formsemestre_id text REFERENCES notes_formsemestre(formsemestre_id)
|
||||||
-- semestre compense par formsemestre_id
|
-- semestre compense par formsemestre_id
|
||||||
) WITH OIDS;
|
) WITH OIDS;
|
||||||
|
|
||||||
|
23
scodoc.py
23
scodoc.py
@ -19,6 +19,9 @@ from flask.cli import with_appcontext
|
|||||||
from app import create_app, cli, db
|
from app import create_app, cli, db
|
||||||
|
|
||||||
from app.auth.models import User, Role, UserRole
|
from app.auth.models import User, Role, UserRole
|
||||||
|
|
||||||
|
from app import models
|
||||||
|
from app.models import ScoPreferences, FormSemestre, FormModalite
|
||||||
from app.views import notes, scolar, absences
|
from app.views import notes, scolar, absences
|
||||||
import app.utils as utils
|
import app.utils as utils
|
||||||
|
|
||||||
@ -35,11 +38,17 @@ def make_shell_context():
|
|||||||
from flask_login import login_user, logout_user, current_user
|
from flask_login import login_user, logout_user, current_user
|
||||||
|
|
||||||
admin_role = Role.query.filter_by(name="SuperAdmin").first()
|
admin_role = Role.query.filter_by(name="SuperAdmin").first()
|
||||||
admin = (
|
if admin_role:
|
||||||
User.query.join(UserRole)
|
admin = (
|
||||||
.filter((UserRole.user_id == User.id) & (UserRole.role_id == admin_role.id))
|
User.query.join(UserRole)
|
||||||
.first()
|
.filter((UserRole.user_id == User.id) & (UserRole.role_id == admin_role.id))
|
||||||
)
|
.first()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
click.echo(
|
||||||
|
"Warning: user database not initialized !\n (use: flask user-db-init)"
|
||||||
|
)
|
||||||
|
admin = None
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"db": db,
|
"db": db,
|
||||||
@ -58,6 +67,10 @@ def make_shell_context():
|
|||||||
"logout_user": logout_user,
|
"logout_user": logout_user,
|
||||||
"admin": admin,
|
"admin": admin,
|
||||||
"ctx": app.test_request_context(),
|
"ctx": app.test_request_context(),
|
||||||
|
# "FormModalite": FormModalite,
|
||||||
|
# "ScoPreferences": ScoPreferences,
|
||||||
|
# "FormSemestre": FormSemestre,
|
||||||
|
"models": models,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user