2021-08-07 15:20:30 +02:00
# -*- coding: UTF-8 -*
""" Définition d ' un étudiant
et données rattachées ( adresses , annotations , . . . )
"""
2022-03-06 22:40:20 +01:00
import datetime
2021-12-26 19:15:47 +01:00
from functools import cached_property
2022-08-07 19:56:25 +02:00
from flask import abort , has_request_context , url_for
2021-12-26 19:15:47 +01:00
from flask import g , request
2022-02-11 18:27:10 +01:00
import sqlalchemy
2022-03-06 22:40:20 +01:00
from sqlalchemy import desc , text
2021-12-21 15:33:21 +01:00
2022-03-06 22:40:20 +01:00
from app import db , log
2021-12-14 23:03:59 +01:00
from app import models
2021-08-07 15:20:30 +02:00
2021-12-30 23:58:38 +01:00
from app . scodoc import notesdb as ndb
2022-01-09 21:02:07 +01:00
from app . scodoc . sco_bac import Baccalaureat
2022-04-12 17:12:51 +02:00
from app . scodoc . sco_exceptions import ScoInvalidParamError
2022-02-12 22:57:46 +01:00
import app . scodoc . sco_utils as scu
2021-08-07 15:20:30 +02:00
class Identite ( db . Model ) :
""" étudiant """
__tablename__ = " identite "
2021-08-15 22:20:07 +02:00
__table_args__ = (
db . UniqueConstraint ( " dept_id " , " code_nip " ) ,
db . UniqueConstraint ( " dept_id " , " code_ine " ) ,
)
2021-08-07 15:20:30 +02:00
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 )
2021-08-07 15:20:30 +02:00
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 ( ) )
2021-08-15 22:20:07 +02:00
# Codes INE et NIP pas unique car le meme etud peut etre ds plusieurs dept
2022-01-10 15:15:26 +01:00
code_nip = db . Column ( db . Text ( ) , index = True )
code_ine = db . Column ( db . Text ( ) , index = True )
2021-08-27 22:16:10 +02:00
# Ancien id ScoDoc7 pour les migrations de bases anciennes
2021-11-01 15:16:51 +01:00
# ne pas utiliser après migrate_scodoc7_dept_archives
2021-08-27 22:16:10 +02:00
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 " )
2022-05-18 20:43:01 +02:00
#
2022-01-09 21:02:07 +01:00
admission = db . relationship ( " Admission " , backref = " identite " , lazy = " dynamic " )
2022-12-01 13:00:14 +01:00
dispense_ues = db . relationship (
" DispenseUE " ,
back_populates = " etud " ,
cascade = " all, delete " ,
passive_deletes = True ,
)
2021-08-07 15:20:30 +02:00
2021-11-20 16:35:09 +01:00
def __repr__ ( self ) :
2022-05-21 07:41:09 +02:00
return (
f " <Etud { self . id } / { self . departement . acronym } { self . nom !r} { self . prenom !r} > "
)
2021-11-20 16:35:09 +01:00
2021-12-26 19:15:47 +01:00
@classmethod
def from_request ( cls , etudid = None , code_nip = None ) :
2022-09-03 11:41:56 +02:00
""" Étudiant à partir de l ' etudid ou du code_nip, soit
2021-12-26 19:15:47 +01:00
passés en argument soit retrouvés directement dans la requête web .
Erreur 404 si inexistant .
"""
args = make_etud_args ( etudid = etudid , code_nip = code_nip )
return Identite . query . filter_by ( * * args ) . first_or_404 ( )
@property
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 ]
2022-02-12 22:57:46 +01:00
def sex_nom ( self , no_accents = False ) - > str :
" ' M. DUPONTÉ ' , ou si no_accents, ' M. DUPONTE ' "
s = f " { self . civilite_str } { ( self . nom_usuel or self . nom ) . upper ( ) } "
if no_accents :
return scu . suppress_accents ( s )
return s
2022-03-06 22:40:20 +01:00
@property
def e ( self ) :
" terminaison en français: ' ne ' , ' ' , ' ou ' (e) ' "
return { " M " : " " , " F " : " e " } . get ( self . civilite , " (e) " )
2021-12-26 19:15:47 +01:00
def nom_disp ( self ) - > str :
" Nom à afficher "
2021-12-04 21:04:09 +01:00
if self . nom_usuel :
return (
( self . nom_usuel + " ( " + self . nom + " ) " ) if self . nom else self . nom_usuel
)
else :
return self . nom
2021-12-26 19:15:47 +01:00
@cached_property
def nomprenom ( self , reverse = False ) - > str :
""" Civilité/nom/prenom pour affichages: " M. Pierre Dupont "
Si reverse , " Dupont Pierre " , sans civilité .
"""
nom = self . nom_usuel or self . nom
prenom = self . prenom_str
if reverse :
fields = ( nom , prenom )
else :
fields = ( self . civilite_str , prenom , nom )
return " " . join ( [ x for x in fields if x ] )
@property
def prenom_str ( self ) :
""" Prénom à afficher. Par exemple: " Jean-Christophe " """
if not self . prenom :
return " "
frags = self . prenom . split ( )
r = [ ]
for frag in frags :
fields = frag . split ( " - " )
r . append ( " - " . join ( [ x . lower ( ) . capitalize ( ) for x in fields ] ) )
return " " . join ( r )
2022-03-26 23:33:57 +01:00
@property
def nom_short ( self ) :
" Nom et début du prénom pour table recap: ' DUPONT Pi. ' "
return f " { ( self . nom_usuel or self . nom or ' ? ' ) . upper ( ) } { ( self . prenom or ' ' ) [ : 2 ] . capitalize ( ) } . "
2021-12-30 23:58:38 +01:00
@cached_property
def sort_key ( self ) - > tuple :
" clé pour tris par ordre alphabétique "
2022-04-03 23:26:13 +02:00
return (
2022-06-23 09:37:35 +02:00
scu . sanitize_string (
2022-07-03 11:30:07 +02:00
self . nom_usuel or self . nom or " " , remove_spaces = False
) . lower ( ) ,
scu . sanitize_string ( self . prenom or " " , remove_spaces = False ) . lower ( ) ,
2022-04-03 23:26:13 +02:00
)
2021-12-30 23:58:38 +01:00
2021-12-11 16:46:15 +01:00
def get_first_email ( self , field = " email " ) - > str :
2021-12-26 19:15:47 +01:00
" Le mail associé à la première adrese de l ' étudiant, ou None "
2022-03-06 22:40:20 +01:00
return getattr ( self . adresses [ 0 ] , field ) if self . adresses . count ( ) > 0 else None
2021-12-11 16:46:15 +01:00
2022-04-28 03:24:37 +02:00
def to_dict_short ( self ) - > dict :
""" Les champs essentiels """
return {
" id " : self . id ,
2022-08-30 19:13:21 +02:00
" civilite " : self . civilite ,
2022-07-29 16:19:40 +02:00
" code_nip " : self . code_nip ,
" code_ine " : self . code_ine ,
" dept_id " : self . dept_id ,
2022-04-28 03:24:37 +02:00
" nom " : self . nom ,
" nom_usuel " : self . nom_usuel ,
" prenom " : self . prenom ,
2022-08-30 19:13:21 +02:00
" sort_key " : self . sort_key ,
2022-04-28 03:24:37 +02:00
}
def to_dict_scodoc7 ( self ) - > dict :
2021-12-30 23:58:38 +01:00
""" Représentation dictionnaire,
compatible ScoDoc7 mais sans infos admission
"""
e = dict ( self . __dict__ )
e . pop ( " _sa_instance_state " , None )
# ScoDoc7 output_formators: (backward compat)
2022-02-10 12:13:24 +01:00
e [ " etudid " ] = self . id
2021-12-30 23:58:38 +01:00
e [ " date_naissance " ] = ndb . DateISOtoDMY ( e [ " date_naissance " ] )
2022-03-06 22:40:20 +01:00
e [ " ne " ] = self . e
2021-12-30 23:58:38 +01:00
return { k : e [ k ] or " " for k in e } # convert_null_outputs_to_empty
2021-12-21 15:33:21 +01:00
def to_dict_bul ( self , include_urls = True ) :
2022-03-16 15:20:23 +01:00
""" Infos exportées dans les bulletins
L ' étudiant, et sa première adresse.
"""
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 ,
2022-03-16 15:20:23 +01:00
" code_ine " : self . code_ine or " " ,
" code_nip " : self . code_nip or " " ,
" date_naissance " : self . date_naissance . strftime ( " %d / % m/ % Y " )
2021-12-05 20:21:51 +01:00
if self . date_naissance
2022-03-16 15:20:23 +01:00
else " " ,
2022-05-11 00:59:51 +02:00
" dept_id " : self . dept_id ,
2022-05-11 04:14:42 +02:00
" dept_acronym " : self . departement . acronym ,
2022-03-16 15:20:23 +01:00
" email " : self . get_first_email ( ) or " " ,
2021-12-11 16:46:15 +01:00
" emailperso " : self . get_first_email ( " emailperso " ) ,
2021-12-05 20:21:51 +01:00
" etudid " : self . id ,
" nom " : self . nom_disp ( ) ,
2022-03-16 15:20:23 +01:00
" prenom " : self . prenom or " " ,
" nomprenom " : self . nomprenom or " " ,
" lieu_naissance " : self . lieu_naissance or " " ,
" dept_naissance " : self . dept_naissance or " " ,
" nationalite " : self . nationalite or " " ,
" boursier " : self . boursier or " " ,
2021-12-05 20:21:51 +01:00
}
2022-08-07 19:56:25 +02:00
if include_urls and has_request_context ( ) :
# test request context so we can use this func in tests under the flask shell
2021-12-21 15:33:21 +01:00
d [ " fiche_url " ] = url_for (
" scolar.ficheEtud " , scodoc_dept = g . scodoc_dept , etudid = self . id
)
2022-03-16 15:20:23 +01:00
d [ " photo_url " ] = sco_photos . get_etud_photo_url ( self . id )
adresse = self . adresses . first ( )
if adresse :
d . update ( adresse . to_dict ( convert_nulls_to_str = True ) )
2022-07-31 20:42:38 +02:00
d [ " id " ] = self . id # a été écrasé par l'id de adresse
2021-12-20 22:53:09 +01:00
return d
2021-12-05 20:21:51 +01:00
2022-07-31 21:44:39 +02:00
def to_dict_api ( self ) - > dict :
""" Représentation dictionnaire pour export API, avec adresses et admission. """
e = dict ( self . __dict__ )
e . pop ( " _sa_instance_state " , None )
admission = self . admission . first ( )
e [ " admission " ] = admission . to_dict ( ) if admission is not None else None
e [ " adresses " ] = [ adr . to_dict ( ) for adr in self . adresses ]
e [ " dept_acronym " ] = self . departement . acronym
e . pop ( " departement " , None )
2022-08-30 19:13:21 +02:00
e [ " sort_key " ] = self . sort_key
2022-07-31 21:44:39 +02:00
return e
2022-07-02 11:17:04 +02:00
def inscriptions ( self ) - > list [ " FormSemestreInscription " ] :
" Liste des inscriptions à des formsemestres, triée, la plus récente en tête "
from app . models . formsemestre import FormSemestre , FormSemestreInscription
return (
FormSemestreInscription . query . join ( FormSemestreInscription . formsemestre )
. filter (
FormSemestreInscription . etudid == self . id ,
)
. order_by ( desc ( FormSemestre . date_debut ) )
. all ( )
)
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
2022-07-02 11:17:04 +02:00
def inscriptions_courantes ( self ) - > list [ " FormSemestreInscription " ] :
2022-03-06 22:40:20 +01:00
""" Liste des inscriptions à des semestres _courants_
( il est rare qu ' il y en ai plus d ' une , mais c ' est possible).
Triées par date de début de semestre décroissante ( le plus récent en premier ) .
"""
from app . models . formsemestre import FormSemestre , FormSemestreInscription
return (
FormSemestreInscription . query . join ( FormSemestreInscription . formsemestre )
. filter (
FormSemestreInscription . etudid == self . id ,
text ( " date_debut < now() and date_fin > now() " ) ,
)
. order_by ( desc ( FormSemestre . date_debut ) )
. all ( )
)
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
2022-03-06 22:40:20 +01:00
def inscription_descr ( self ) - > dict :
""" Description de l ' état d ' inscription """
inscription_courante = self . inscription_courante ( )
if inscription_courante :
titre_sem = inscription_courante . formsemestre . titre_mois ( )
2022-09-30 20:55:09 +02:00
if inscription_courante . etat == scu . DEMISSION :
inscr_txt = " Démission de "
elif inscription_courante . etat == scu . DEF :
inscr_txt = " Défaillant dans "
else :
inscr_txt = " Inscrit en "
2022-03-06 22:40:20 +01:00
return {
" etat_in_cursem " : inscription_courante . etat ,
" inscription_courante " : inscription_courante ,
" inscription " : titre_sem ,
2022-09-30 20:55:09 +02:00
" inscription_str " : inscr_txt + " " + titre_sem ,
2022-03-06 22:40:20 +01:00
" situation " : self . descr_situation_etud ( ) ,
}
else :
if self . formsemestre_inscriptions :
# cherche l'inscription la plus récente:
fin_dernier_sem = max (
[
inscr . formsemestre . date_debut
for inscr in self . formsemestre_inscriptions
]
)
if fin_dernier_sem > datetime . date . today ( ) :
inscription = " futur "
situation = " futur élève "
else :
inscription = " ancien "
situation = " ancien élève "
else :
inscription = ( " non inscrit " , )
situation = inscription
return {
" etat_in_cursem " : " ? " ,
" inscription_courante " : None ,
" inscription " : inscription ,
" inscription_str " : inscription ,
" situation " : situation ,
}
2022-09-30 16:20:51 +02:00
def inscription_etat ( self , formsemestre_id : int ) - > str :
2022-07-02 11:17:04 +02:00
""" État 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
2022-03-06 22:40:20 +01:00
def descr_situation_etud ( self ) - > str :
""" Chaîne décrivant la situation _actuelle_ de l ' étudiant.
Exemple :
" inscrit en BUT R&T semestre 2 FI (Jan 2022 - Jul 2022) le 16/01/2022 "
ou
" non inscrit "
"""
inscriptions_courantes = self . inscriptions_courantes ( )
if inscriptions_courantes :
inscr = inscriptions_courantes [ 0 ]
if inscr . etat == scu . INSCRIT :
situation = f " inscrit { self . e } en { inscr . formsemestre . titre_mois ( ) } "
# Cherche la date d'inscription dans scolar_events:
events = models . ScolarEvent . query . filter_by (
etudid = self . id ,
formsemestre_id = inscr . formsemestre . id ,
event_type = " INSCRIPTION " ,
) . all ( )
if not events :
log (
f " *** situation inconsistante pour { self } (inscrit mais pas d ' event) "
)
2022-03-21 14:33:38 +01:00
situation + = " (inscription non enregistrée) " # ???
2022-03-06 22:40:20 +01:00
else :
date_ins = events [ 0 ] . event_date
2022-03-21 14:33:38 +01:00
situation + = date_ins . strftime ( " le %d / % m/ % Y " )
2022-04-21 16:35:27 +02:00
elif inscr . etat == scu . DEF :
situation = f " défaillant en { inscr . formsemestre . titre_mois ( ) } "
event = (
models . ScolarEvent . query . filter_by (
etudid = self . id ,
formsemestre_id = inscr . formsemestre . id ,
event_type = " DEFAILLANCE " ,
)
. order_by ( models . ScolarEvent . event_date )
. first ( )
)
if not event :
log (
f " *** situation inconsistante pour { self } (def mais pas d ' event) "
)
situation + = " ??? " # ???
else :
date_def = event . event_date
situation + = date_def . strftime ( " le %d / % m/ % Y " )
2022-03-06 22:40:20 +01:00
else :
situation = f " démission de { inscr . formsemestre . titre_mois ( ) } "
# Cherche la date de demission dans scolar_events:
2022-04-21 16:35:27 +02:00
event = (
models . ScolarEvent . query . filter_by (
etudid = self . id ,
formsemestre_id = inscr . formsemestre . id ,
event_type = " DEMISSION " ,
)
. order_by ( models . ScolarEvent . event_date )
. first ( )
)
if not event :
2022-03-06 22:40:20 +01:00
log (
f " *** situation inconsistante pour { self } (demission mais pas d ' event) "
)
2022-04-21 16:35:27 +02:00
situation + = " ??? " # ???
2022-03-06 22:40:20 +01:00
else :
2022-04-21 16:35:27 +02:00
date_dem = event . event_date
situation + = date_dem . strftime ( " le %d / % m/ % Y " )
2022-03-06 22:40:20 +01:00
else :
situation = " non inscrit " + self . e
return situation
2022-06-30 23:49:39 +02:00
def etat_civil_pv ( self , line_sep = " \n " ) - > str :
""" Présentation, pour PV jury
M . Pierre Dupont
n ° 12345678
né ( e ) le 7 / 06 / 1974
à Paris
"""
return f """ { self . nomprenom } { line_sep } n° { self . code_nip or " " } { line_sep } né { self . e } le { self . date_naissance . strftime ( " %d / % m/ % Y " ) if self . date_naissance else " " } { line_sep } à { self . lieu_naissance or " " } """
2022-03-06 22:40:20 +01:00
def photo_html ( self , title = None , size = " small " ) - > str :
""" HTML img tag for the photo, either in small size (h90)
or original size ( size == " orig " )
"""
from app . scodoc import sco_photos
# sco_photo traite des dicts:
return sco_photos . etud_photo_html (
etud = dict (
etudid = self . id ,
code_nip = self . code_nip ,
nomprenom = self . nomprenom ,
nom_disp = self . nom_disp ( ) ,
photo_filename = self . photo_filename ,
) ,
title = title ,
size = size ,
)
2021-08-07 15:20:30 +02:00
2021-12-26 19:15:47 +01:00
def make_etud_args (
etudid = None , code_nip = None , use_request = True , raise_exc = False , abort_404 = True
) - > dict :
""" forme args dict pour requete recherche etudiant
On peut specifier etudid
ou bien ( si use_request ) cherche dans la requete http : etudid , code_nip , code_ine
( dans cet ordre ) .
Résultat : dict avec soit " etudid " , soit " code_nip " , soit " code_ine "
"""
args = None
if etudid :
2022-04-05 22:23:55 +02:00
try :
args = { " etudid " : int ( etudid ) }
except ValueError as exc :
2022-04-12 17:12:51 +02:00
raise ScoInvalidParamError ( ) from exc
2021-12-26 19:15:47 +01:00
elif code_nip :
args = { " code_nip " : code_nip }
elif use_request : # use form from current request (Flask global)
if request . method == " POST " :
vals = request . form
elif request . method == " GET " :
vals = request . args
else :
vals = { }
2022-03-27 10:49:45 +02:00
try :
if " etudid " in vals :
args = { " etudid " : int ( vals [ " etudid " ] ) }
elif " code_nip " in vals :
args = { " code_nip " : str ( vals [ " code_nip " ] ) }
elif " code_ine " in vals :
args = { " code_ine " : str ( vals [ " code_ine " ] ) }
except ValueError :
args = { }
2021-12-26 19:15:47 +01:00
if not args :
if abort_404 :
abort ( 404 , " pas d ' étudiant sélectionné " )
elif raise_exc :
raise ValueError ( " make_etud_args: pas d ' étudiant sélectionné ! " )
return args
2021-08-07 15:20:30 +02:00
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 ,
2022-05-26 03:55:03 +02:00
db . ForeignKey ( " identite.id " , ondelete = " CASCADE " ) ,
2021-08-07 15:20:30 +02:00
)
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
)
2021-08-07 15:20:30 +02:00
description = db . Column ( db . Text )
2022-03-16 15:20:23 +01:00
def to_dict ( self , convert_nulls_to_str = False ) :
""" Représentation dictionnaire, """
e = dict ( self . __dict__ )
e . pop ( " _sa_instance_state " , None )
if convert_nulls_to_str :
return { k : e [ k ] or " " for k in e }
return e
2021-08-07 15:20:30 +02:00
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 ,
2022-05-26 03:55:03 +02:00
db . ForeignKey ( " identite.id " , ondelete = " CASCADE " ) ,
2021-08-07 15:20:30 +02:00
)
# 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 )
2022-01-09 21:02:07 +01:00
def get_bac ( self ) - > Baccalaureat :
" Le bac. utiliser bac.abbrev() pour avoir une chaine de caractères. "
return Baccalaureat ( self . bac , specialite = self . specialite )
2022-02-11 18:27:10 +01:00
def to_dict ( self , no_nulls = False ) :
""" Représentation dictionnaire, """
2022-05-22 03:26:39 +02:00
d = dict ( self . __dict__ )
d . pop ( " _sa_instance_state " , None )
2022-02-11 18:27:10 +01:00
if no_nulls :
2022-05-22 03:26:39 +02:00
for k in d . keys ( ) :
if d [ k ] is None :
2022-02-11 18:27:10 +01:00
col_type = getattr (
sqlalchemy . inspect ( models . Admission ) . columns , " apb_groupe "
) . expression . type
if isinstance ( col_type , sqlalchemy . Text ) :
2022-05-22 03:26:39 +02:00
d [ k ] = " "
2022-02-11 18:27:10 +01:00
elif isinstance ( col_type , sqlalchemy . Integer ) :
2022-05-22 03:26:39 +02:00
d [ k ] = 0
2022-02-11 18:27:10 +01:00
elif isinstance ( col_type , sqlalchemy . Boolean ) :
2022-05-22 03:26:39 +02:00
d [ k ] = False
return d
2022-02-11 18:27:10 +01:00
2021-08-07 15:20:30 +02:00
# 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 ,
2022-05-26 03:55:03 +02:00
db . ForeignKey ( " identite.id " , ondelete = " CASCADE " ) ,
2021-08-07 15:20:30 +02:00
)
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 )
2021-08-29 21:21:41 +02:00
dept_id = db . Column ( db . Integer , db . ForeignKey ( " departement.id " ) , index = True )
2021-08-07 15:20:30 +02:00
tag_id = db . synonym ( " id " )
2021-08-15 22:13:41 +02:00
title = db . Column ( db . Text ( ) , nullable = False , unique = True )
2021-08-07 15:20:30 +02:00
# 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 " )
) ,
2021-08-07 15:20:30 +02:00
)
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 ( ) )
2021-08-14 18:54:32 +02:00
etudid = db . Column ( db . Integer ) # sans contrainte (compat ScoDoc 7))
author = db . Column ( db . Text ) # le pseudo (user_name), was zope_authenticated_user
2021-08-07 15:20:30 +02:00
comment = db . Column ( db . Text )