ScoDoc/app/models/etudiants.py

255 lines
8.4 KiB
Python
Raw Normal View History

# -*- coding: UTF-8 -*
"""Définition d'un étudiant
et données rattachées (adresses, annotations, ...)
"""
2021-12-21 15:33:21 +01:00
from flask import g, url_for
from app import db
from app import models
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"
__table_args__ = (
db.UniqueConstraint("dept_id", "code_nip"),
db.UniqueConstraint("dept_id", "code_ine"),
)
id = db.Column(db.Integer, primary_key=True)
etudid = db.synonym("id")
2021-08-13 00:34:58 +02:00
dept_id = db.Column(db.Integer, db.ForeignKey("departement.id"), index=True)
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())
# Codes INE et NIP pas unique car le meme etud peut etre ds plusieurs dept
code_nip = db.Column(db.Text())
code_ine = db.Column(db.Text())
# Ancien id ScoDoc7 pour les migrations de bases anciennes
# ne pas utiliser après migrate_scodoc7_dept_archives
scodoc7_id = db.Column(db.Text(), nullable=True)
2021-09-28 09:14:04 +02:00
#
2021-12-05 20:21:51 +01:00
adresses = db.relationship("Adresse", lazy="dynamic", backref="etud")
2021-09-28 09:14:04 +02:00
billets = db.relationship("BilletAbsence", backref="etudiant", lazy="dynamic")
def __repr__(self):
return f"<Etud {self.id} {self.nom} {self.prenom}>"
2021-12-04 21:04:09 +01:00
def civilite_str(self):
"""returns 'M.' ou 'Mme' ou '' (pour le genre neutre,
personnes ne souhaitant pas d'affichage).
"""
return {"M": "M.", "F": "Mme", "X": ""}[self.civilite]
def nom_disp(self):
"nom à afficher"
if self.nom_usuel:
return (
(self.nom_usuel + " (" + self.nom + ")") if self.nom else self.nom_usuel
)
else:
return self.nom
def get_first_email(self, field="email") -> str:
"le mail associé à la première adrese de l'étudiant, ou None"
return self.adresses[0].email or None if self.adresses.count() > 0 else None
2021-12-21 15:33:21 +01:00
def to_dict_bul(self, include_urls=True):
2021-12-05 20:21:51 +01:00
"""Infos exportées dans les bulletins"""
2021-12-20 22:53:09 +01:00
from app.scodoc import sco_photos
d = {
2021-12-05 20:21:51 +01:00
"civilite": self.civilite,
2021-12-21 15:10:20 +01:00
"code_ine": self.code_ine,
"code_nip": self.code_nip,
2021-12-05 20:21:51 +01:00
"date_naissance": self.date_naissance.isoformat()
if self.date_naissance
else None,
"email": self.get_first_email(),
"emailperso": self.get_first_email("emailperso"),
2021-12-05 20:21:51 +01:00
"etudid": self.id,
"nom": self.nom_disp(),
"prenom": self.prenom,
}
2021-12-21 15:33:21 +01:00
if include_urls:
d["fiche_url"] = url_for(
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=self.id
)
2021-12-20 22:53:09 +01:00
d["photo_url"] = (sco_photos.get_etud_photo_url(self.id),)
return d
2021-12-05 20:21:51 +01:00
2021-12-04 21:04:09 +01:00
def inscription_courante(self):
"""La première inscription à un formsemestre _actuellement_ en cours.
None s'il n'y en a pas (ou plus, ou pas encore).
"""
r = [
ins
for ins in self.formsemestre_inscriptions
if ins.formsemestre.est_courant()
]
return r[0] if r else None
2021-12-23 19:28:25 +01:00
def inscription_courante_date(self, date_debut, date_fin):
2021-12-29 14:41:33 +01:00
"""La première inscription à un formsemestre incluant la
période [date_debut, date_fin]
"""
2021-12-23 19:28:25 +01:00
r = [
ins
for ins in self.formsemestre_inscriptions
2021-12-29 14:41:33 +01:00
if ins.formsemestre.contient_periode(date_debut, date_fin)
2021-12-23 19:28:25 +01:00
]
return r[0] if r else None
def etat_inscription(self, formsemestre_id):
"""etat de l'inscription de cet étudiant au semestre:
False si pas inscrit, ou scu.INSCRIT, DEMISSION, DEF
"""
# voir si ce n'est pas trop lent:
ins = models.FormSemestreInscription.query.filter_by(
etudid=self.id, formsemestre_id=formsemestre_id
).first()
if ins:
return ins.etat
return False
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)
2021-08-10 00:23:30 +02:00
typeadresse = db.Column(
db.Text, default="domicile", server_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)
dept_id = db.Column(db.Integer, db.ForeignKey("departement.id"), index=True)
tag_id = db.synonym("id")
title = db.Column(db.Text(), nullable=False, unique=True)
# Association tag <-> module
itemsuivi_tags_assoc = db.Table(
"itemsuivi_tags_assoc",
2021-11-27 19:04:30 +01:00
db.Column(
"tag_id", db.Integer, db.ForeignKey("itemsuivi_tags.id", ondelete="CASCADE")
),
db.Column(
"itemsuivi_id", db.Integer, db.ForeignKey("itemsuivi.id", ondelete="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 (compat ScoDoc 7))
author = db.Column(db.Text) # le pseudo (user_name), was zope_authenticated_user
comment = db.Column(db.Text)