forked from ScoDoc/ScoDoc
WIP: modernisation code jurys
This commit is contained in:
parent
e0208d0650
commit
320cfbebc8
@ -44,7 +44,7 @@ from app.scodoc import sco_cursus_dut
|
|||||||
class SituationEtudCursusBUT(sco_cursus_dut.SituationEtudCursusClassic):
|
class SituationEtudCursusBUT(sco_cursus_dut.SituationEtudCursusClassic):
|
||||||
"""Pour compat ScoDoc 7: à revoir pour le BUT"""
|
"""Pour compat ScoDoc 7: à revoir pour le BUT"""
|
||||||
|
|
||||||
def __init__(self, etud: dict, formsemestre_id: int, res: ResultatsSemestreBUT):
|
def __init__(self, etud: Identite, formsemestre_id: int, res: ResultatsSemestreBUT):
|
||||||
super().__init__(etud, formsemestre_id, res)
|
super().__init__(etud, formsemestre_id, res)
|
||||||
# Ajustements pour le BUT
|
# Ajustements pour le BUT
|
||||||
self.can_compensate_with_prev = False # jamais de compensation à la mode DUT
|
self.can_compensate_with_prev = False # jamais de compensation à la mode DUT
|
||||||
|
@ -359,14 +359,15 @@ class Identite(models.ScoDocModel):
|
|||||||
"Le mail associé à la première adresse de l'étudiant, ou None"
|
"Le mail associé à la première adresse de l'étudiant, ou None"
|
||||||
return getattr(self.adresses[0], field) if self.adresses.count() > 0 else None
|
return getattr(self.adresses[0], field) if self.adresses.count() > 0 else None
|
||||||
|
|
||||||
def get_formsemestres(self) -> list:
|
def get_formsemestres(self, recent_first=True) -> list:
|
||||||
"""Liste des formsemestres dans lesquels l'étudiant est (a été) inscrit,
|
"""Liste des formsemestres dans lesquels l'étudiant est (a été) inscrit,
|
||||||
triée par date_debut
|
triée par date_debut, le plus récent d'abord (comme "sems" de scodoc7)
|
||||||
|
(si recent_first=False, le plus ancien en tête)
|
||||||
"""
|
"""
|
||||||
return sorted(
|
return sorted(
|
||||||
[ins.formsemestre for ins in self.formsemestre_inscriptions],
|
[ins.formsemestre for ins in self.formsemestre_inscriptions],
|
||||||
key=attrgetter("date_debut"),
|
key=attrgetter("date_debut"),
|
||||||
reverse=True,
|
reverse=recent_first,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_modimpls_by_formsemestre(
|
def get_modimpls_by_formsemestre(
|
||||||
|
@ -46,6 +46,8 @@ class UniteEns(models.ScoDocModel):
|
|||||||
# coef UE, utilise seulement si l'option use_ue_coefs est activée:
|
# coef UE, utilise seulement si l'option use_ue_coefs est activée:
|
||||||
coefficient = db.Column(db.Float)
|
coefficient = db.Column(db.Float)
|
||||||
|
|
||||||
|
# id de l'élément Apogée du RCUE (utilisé pour les UEs de sem. pair du BUT)
|
||||||
|
code_apogee_rcue = db.Column(db.String(APO_CODE_STR_LEN))
|
||||||
# coef. pour le calcul de moyennes de RCUE. Par défaut, 1.
|
# coef. pour le calcul de moyennes de RCUE. Par défaut, 1.
|
||||||
coef_rcue = db.Column(db.Float, nullable=False, default=1.0, server_default="1.0")
|
coef_rcue = db.Column(db.Float, nullable=False, default=1.0, server_default="1.0")
|
||||||
|
|
||||||
|
@ -48,9 +48,9 @@ import numpy as np
|
|||||||
|
|
||||||
|
|
||||||
from app import log
|
from app import log
|
||||||
|
from app.but import jury_but
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.comp.res_but import ResultatsSemestreBUT
|
|
||||||
from app.models import (
|
from app.models import (
|
||||||
ApcValidationAnnee,
|
ApcValidationAnnee,
|
||||||
ApcValidationRCUE,
|
ApcValidationRCUE,
|
||||||
@ -132,7 +132,7 @@ class ApoEtud(dict):
|
|||||||
"Vrai si BUT"
|
"Vrai si BUT"
|
||||||
self.col_elts = {}
|
self.col_elts = {}
|
||||||
"{'V1RT': {'R': 'ADM', 'J': '', 'B': 20, 'N': '12.14'}}"
|
"{'V1RT': {'R': 'ADM', 'J': '', 'B': 20, 'N': '12.14'}}"
|
||||||
self.etud: Identite = None
|
self.etud: Identite | None = None
|
||||||
"etudiant ScoDoc associé"
|
"etudiant ScoDoc associé"
|
||||||
self.etat = None # ETUD_OK, ...
|
self.etat = None # ETUD_OK, ...
|
||||||
self.is_nar = False
|
self.is_nar = False
|
||||||
@ -171,24 +171,18 @@ class ApoEtud(dict):
|
|||||||
Sinon, cherche le semestre, et met l'état à ETUD_OK ou ETUD_NON_INSCRIT.
|
Sinon, cherche le semestre, et met l'état à ETUD_OK ou ETUD_NON_INSCRIT.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# futur: #WIP
|
self.etud = Identite.query.filter_by(
|
||||||
# etud: Identite = Identite.query.filter_by(code_nip=self["nip"], dept_id=g.scodoc_dept_id).first()
|
code_nip=self["nip"], dept_id=g.scodoc_dept_id
|
||||||
# self.etud = etud
|
).first()
|
||||||
etuds = sco_etud.get_etud_info(code_nip=self["nip"], filled=True)
|
if not self.etud:
|
||||||
if not etuds:
|
|
||||||
# pas dans ScoDoc
|
# pas dans ScoDoc
|
||||||
self.etud = None
|
|
||||||
self.log.append("non inscrit dans ScoDoc")
|
self.log.append("non inscrit dans ScoDoc")
|
||||||
self.etat = ETUD_ORPHELIN
|
self.etat = ETUD_ORPHELIN
|
||||||
else:
|
else:
|
||||||
# futur: #WIP
|
|
||||||
# formsemestre_ids = {
|
|
||||||
# ins.formsemestre_id for ins in etud.formsemestre_inscriptions
|
|
||||||
# }
|
|
||||||
# in_formsemestre_ids = formsemestre_ids.intersection(etape_formsemestre_ids)
|
|
||||||
self.etud = etuds[0]
|
|
||||||
# cherche le semestre ScoDoc correspondant à l'un de ceux de l'etape:
|
# cherche le semestre ScoDoc correspondant à l'un de ceux de l'etape:
|
||||||
formsemestre_ids = {s["formsemestre_id"] for s in self.etud["sems"]}
|
formsemestre_ids = {
|
||||||
|
ins.formsemestre_id for ins in self.etud.formsemestre_inscriptions
|
||||||
|
}
|
||||||
in_formsemestre_ids = formsemestre_ids.intersection(etape_formsemestre_ids)
|
in_formsemestre_ids = formsemestre_ids.intersection(etape_formsemestre_ids)
|
||||||
if not in_formsemestre_ids:
|
if not in_formsemestre_ids:
|
||||||
self.log.append(
|
self.log.append(
|
||||||
@ -267,13 +261,17 @@ class ApoEtud(dict):
|
|||||||
Args:
|
Args:
|
||||||
code (str): code apo de l'element cherché
|
code (str): code apo de l'element cherché
|
||||||
sem (dict): semestre dans lequel on cherche l'élément
|
sem (dict): semestre dans lequel on cherche l'élément
|
||||||
|
|
||||||
|
Utilise notamment:
|
||||||
cur_sem (dict): semestre "courant" pour résultats annuels (VET)
|
cur_sem (dict): semestre "courant" pour résultats annuels (VET)
|
||||||
autre_sem (dict): autre semestre utilisé pour calculer les résultats annuels (VET)
|
autre_sem (dict): autre semestre utilisé pour calculer les résultats annuels (VET)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict: with N, B, J, R keys, ou None si elt non trouvé
|
dict: with N, B, J, R keys, ou None si elt non trouvé
|
||||||
"""
|
"""
|
||||||
etudid = self.etud["etudid"]
|
if not self.etud:
|
||||||
|
return None
|
||||||
|
etudid = self.etud.id
|
||||||
if not self.cur_res:
|
if not self.cur_res:
|
||||||
log("search_elt_in_sem: no cur_res !")
|
log("search_elt_in_sem: no cur_res !")
|
||||||
return None
|
return None
|
||||||
@ -377,6 +375,8 @@ class ApoEtud(dict):
|
|||||||
|
|
||||||
if module_code_found:
|
if module_code_found:
|
||||||
return VOID_APO_RES
|
return VOID_APO_RES
|
||||||
|
# RCUE du BUT
|
||||||
|
deca = jury_but.DecisionsProposeesAnnee(self.etud, formsemestre)
|
||||||
#
|
#
|
||||||
return None # element Apogee non trouvé dans ce semestre
|
return None # element Apogee non trouvé dans ce semestre
|
||||||
|
|
||||||
|
@ -751,7 +751,7 @@ def formsemestre_get_assiduites_count(
|
|||||||
) -> tuple[int, int, int]:
|
) -> tuple[int, int, int]:
|
||||||
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
||||||
tuple (nb abs non justifiées, nb abs justifiées, nb abs total)
|
tuple (nb abs non justifiées, nb abs justifiées, nb abs total)
|
||||||
Utilise un cache.
|
Utilise un cache (si moduleimpl_id n'est pas spécifié).
|
||||||
"""
|
"""
|
||||||
metrique = sco_preferences.get_preference("assi_metrique", formsemestre.id)
|
metrique = sco_preferences.get_preference("assi_metrique", formsemestre.id)
|
||||||
return get_assiduites_count_in_interval(
|
return get_assiduites_count_in_interval(
|
||||||
@ -779,7 +779,7 @@ def get_assiduites_count_in_interval(
|
|||||||
"""Les comptes d'absences de cet étudiant entre ces deux dates, incluses:
|
"""Les comptes d'absences de cet étudiant entre ces deux dates, incluses:
|
||||||
tuple (nb abs non justifiées, nb abs justifiées, nb abs total)
|
tuple (nb abs non justifiées, nb abs justifiées, nb abs total)
|
||||||
On peut spécifier les dates comme datetime ou iso.
|
On peut spécifier les dates comme datetime ou iso.
|
||||||
Utilise un cache.
|
Utilise un cache (si moduleimpl_id n'est pas spécifié).
|
||||||
"""
|
"""
|
||||||
date_debut_iso = date_debut_iso or date_debut.strftime("%Y-%m-%d")
|
date_debut_iso = date_debut_iso or date_debut.strftime("%Y-%m-%d")
|
||||||
date_fin_iso = date_fin_iso or date_fin.strftime("%Y-%m-%d")
|
date_fin_iso = date_fin_iso or date_fin.strftime("%Y-%m-%d")
|
||||||
|
@ -34,13 +34,13 @@ from app.scodoc import sco_cursus_dut
|
|||||||
|
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre, Identite
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
|
|
||||||
|
|
||||||
# SituationEtudParcours -> get_situation_etud_cursus
|
# SituationEtudParcours -> get_situation_etud_cursus
|
||||||
def get_situation_etud_cursus(
|
def get_situation_etud_cursus(
|
||||||
etud: dict, formsemestre_id: int
|
etud: Identite, formsemestre_id: int
|
||||||
) -> sco_cursus_dut.SituationEtudCursus:
|
) -> sco_cursus_dut.SituationEtudCursus:
|
||||||
"""renvoie une instance de SituationEtudCursus (ou sous-classe spécialisée)"""
|
"""renvoie une instance de SituationEtudCursus (ou sous-classe spécialisée)"""
|
||||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
from app import db
|
from app import db
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import FormSemestre, UniteEns, ScolarAutorisationInscription
|
from app.models import FormSemestre, Identite, ScolarAutorisationInscription, UniteEns
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
@ -115,14 +115,22 @@ class SituationEtudCursus:
|
|||||||
class SituationEtudCursusClassic(SituationEtudCursus):
|
class SituationEtudCursusClassic(SituationEtudCursus):
|
||||||
"Semestre dans un parcours"
|
"Semestre dans un parcours"
|
||||||
|
|
||||||
def __init__(self, etud: dict, formsemestre_id: int, nt: NotesTableCompat):
|
def __init__(self, etud: Identite, formsemestre_id: int, nt: NotesTableCompat):
|
||||||
"""
|
"""
|
||||||
etud: dict filled by fill_etuds_info()
|
etud: dict filled by fill_etuds_info()
|
||||||
"""
|
"""
|
||||||
|
assert formsemestre_id == nt.formsemestre.id
|
||||||
self.etud = etud
|
self.etud = etud
|
||||||
self.etudid = etud["etudid"]
|
self.etudid = etud.id
|
||||||
self.formsemestre_id = formsemestre_id
|
self.formsemestre_id = formsemestre_id
|
||||||
self.sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
self.formsemestres: list[FormSemestre] = []
|
||||||
|
"les semestres parcourus, le plus ancien en tête"
|
||||||
|
self.sem = sco_formsemestre.get_formsemestre(
|
||||||
|
formsemestre_id
|
||||||
|
) # TODO utiliser formsemestres
|
||||||
|
self.cur_sem: FormSemestre = nt.formsemestre
|
||||||
|
self.can_compensate: set[int] = set()
|
||||||
|
"les formsemestre_id qui peuvent compenser le courant"
|
||||||
self.nt: NotesTableCompat = nt
|
self.nt: NotesTableCompat = nt
|
||||||
self.formation = self.nt.formsemestre.formation
|
self.formation = self.nt.formsemestre.formation
|
||||||
self.parcours = self.nt.parcours
|
self.parcours = self.nt.parcours
|
||||||
@ -130,18 +138,20 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
# pour le DUT, le dernier est toujours S4.
|
# pour le DUT, le dernier est toujours S4.
|
||||||
# Ici: terminal si semestre == NB_SEM ou bien semestre_id==-1
|
# Ici: terminal si semestre == NB_SEM ou bien semestre_id==-1
|
||||||
# (licences et autres formations en 1 seule session))
|
# (licences et autres formations en 1 seule session))
|
||||||
self.semestre_non_terminal = self.sem["semestre_id"] != self.parcours.NB_SEM
|
self.semestre_non_terminal = self.cur_sem.semestre_id != self.parcours.NB_SEM
|
||||||
if self.sem["semestre_id"] == NO_SEMESTRE_ID:
|
if self.cur_sem.semestre_id == NO_SEMESTRE_ID:
|
||||||
self.semestre_non_terminal = False
|
self.semestre_non_terminal = False
|
||||||
# Liste des semestres du parcours de cet étudiant:
|
# Liste des semestres du parcours de cet étudiant:
|
||||||
self._comp_semestres()
|
self._comp_semestres()
|
||||||
# Determine le semestre "precedent"
|
# Determine le semestre "precedent"
|
||||||
self.prev_formsemestre_id = self._search_prev()
|
self._search_prev()
|
||||||
# Verifie barres
|
# Verifie barres
|
||||||
self._comp_barres()
|
self._comp_barres()
|
||||||
# Verifie compensation
|
# Verifie compensation
|
||||||
if self.prev and self.sem["gestion_compensation"]:
|
if self.prev_formsemestre and self.cur_sem.gestion_compensation:
|
||||||
self.can_compensate_with_prev = self.prev["can_compensate"]
|
self.can_compensate_with_prev = (
|
||||||
|
self.prev_formsemestre.id in self.can_compensate
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.can_compensate_with_prev = False
|
self.can_compensate_with_prev = False
|
||||||
|
|
||||||
@ -170,14 +180,14 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
if rule.conclusion[0] in self.parcours.UNUSED_CODES:
|
if rule.conclusion[0] in self.parcours.UNUSED_CODES:
|
||||||
continue
|
continue
|
||||||
# Saute regles REDOSEM si pas de semestres decales:
|
# Saute regles REDOSEM si pas de semestres decales:
|
||||||
if (not self.sem["gestion_semestrielle"]) and rule.conclusion[
|
if (not self.cur_sem.gestion_semestrielle) and rule.conclusion[
|
||||||
3
|
3
|
||||||
] == "REDOSEM":
|
] == "REDOSEM":
|
||||||
continue
|
continue
|
||||||
if rule.match(state):
|
if rule.match(state):
|
||||||
if rule.conclusion[0] == ADC:
|
if rule.conclusion[0] == ADC:
|
||||||
# dans les regles on ne peut compenser qu'avec le PRECEDENT:
|
# dans les regles on ne peut compenser qu'avec le PRECEDENT:
|
||||||
fiduc = self.prev_formsemestre_id
|
fiduc = self.prev_formsemestre.id
|
||||||
assert fiduc
|
assert fiduc
|
||||||
else:
|
else:
|
||||||
fiduc = None
|
fiduc = None
|
||||||
@ -203,8 +213,8 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
"Phrase d'explication pour le code devenir"
|
"Phrase d'explication pour le code devenir"
|
||||||
if not devenir:
|
if not devenir:
|
||||||
return ""
|
return ""
|
||||||
s = self.sem["semestre_id"] # numero semestre courant
|
s_idx = self.cur_sem.semestre_id # numero semestre courant
|
||||||
if s < 0: # formation sans semestres (eg licence)
|
if s_idx < 0: # formation sans semestres (eg licence)
|
||||||
next_s = 1
|
next_s = 1
|
||||||
else:
|
else:
|
||||||
next_s = self._get_next_semestre_id()
|
next_s = self._get_next_semestre_id()
|
||||||
@ -219,27 +229,27 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
elif devenir == REO:
|
elif devenir == REO:
|
||||||
return "Réorienté"
|
return "Réorienté"
|
||||||
elif devenir == REDOANNEE:
|
elif devenir == REDOANNEE:
|
||||||
return "Redouble année (recommence %s%s)" % (SA, (s - 1))
|
return "Redouble année (recommence %s%s)" % (SA, (s_idx - 1))
|
||||||
elif devenir == REDOSEM:
|
elif devenir == REDOSEM:
|
||||||
return "Redouble semestre (recommence en %s%s)" % (SA, s)
|
return "Redouble semestre (recommence en %s%s)" % (SA, s_idx)
|
||||||
elif devenir == RA_OR_NEXT:
|
elif devenir == RA_OR_NEXT:
|
||||||
return passage + ", ou redouble année (en %s%s)" % (SA, (s - 1))
|
return passage + ", ou redouble année (en %s%s)" % (SA, (s_idx - 1))
|
||||||
elif devenir == RA_OR_RS:
|
elif devenir == RA_OR_RS:
|
||||||
return "Redouble semestre %s%s, ou redouble année (en %s%s)" % (
|
return "Redouble semestre %s%s, ou redouble année (en %s%s)" % (
|
||||||
SA,
|
SA,
|
||||||
s,
|
s_idx,
|
||||||
SA,
|
SA,
|
||||||
s - 1,
|
s_idx - 1,
|
||||||
)
|
)
|
||||||
elif devenir == RS_OR_NEXT:
|
elif devenir == RS_OR_NEXT:
|
||||||
return passage + ", ou semestre %s%s" % (SA, s)
|
return passage + ", ou semestre %s%s" % (SA, s_idx)
|
||||||
elif devenir == NEXT_OR_NEXT2:
|
elif devenir == NEXT_OR_NEXT2:
|
||||||
return passage + ", ou en semestre %s%s" % (
|
return passage + ", ou en semestre %s%s" % (
|
||||||
SA,
|
SA,
|
||||||
s + 2,
|
s_idx + 2,
|
||||||
) # coherent avec get_next_semestre_ids
|
) # coherent avec get_next_semestre_ids
|
||||||
elif devenir == NEXT2:
|
elif devenir == NEXT2:
|
||||||
return "Passe en %s%s" % (SA, s + 2)
|
return "Passe en %s%s" % (SA, s_idx + 2)
|
||||||
else:
|
else:
|
||||||
log("explique_devenir: code devenir inconnu: %s" % devenir)
|
log("explique_devenir: code devenir inconnu: %s" % devenir)
|
||||||
return "Code devenir inconnu !"
|
return "Code devenir inconnu !"
|
||||||
@ -258,7 +268,7 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
|
|
||||||
def _sems_validated(self, exclude_current=False):
|
def _sems_validated(self, exclude_current=False):
|
||||||
"True si semestres du parcours validés"
|
"True si semestres du parcours validés"
|
||||||
if self.sem["semestre_id"] == NO_SEMESTRE_ID:
|
if self.cur_sem.semestre_id == NO_SEMESTRE_ID:
|
||||||
# mono-semestre: juste celui ci
|
# mono-semestre: juste celui ci
|
||||||
decision = self.nt.get_etud_decision_sem(self.etudid)
|
decision = self.nt.get_etud_decision_sem(self.etudid)
|
||||||
return decision and code_semestre_validant(decision["code"])
|
return decision and code_semestre_validant(decision["code"])
|
||||||
@ -266,8 +276,8 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
to_validate = set(
|
to_validate = set(
|
||||||
range(1, self.parcours.NB_SEM + 1)
|
range(1, self.parcours.NB_SEM + 1)
|
||||||
) # ensemble des indices à valider
|
) # ensemble des indices à valider
|
||||||
if exclude_current and self.sem["semestre_id"] in to_validate:
|
if exclude_current and self.cur_sem.semestre_id in to_validate:
|
||||||
to_validate.remove(self.sem["semestre_id"])
|
to_validate.remove(self.cur_sem.semestre_id)
|
||||||
return self._sem_list_validated(to_validate)
|
return self._sem_list_validated(to_validate)
|
||||||
|
|
||||||
def can_jump_to_next2(self):
|
def can_jump_to_next2(self):
|
||||||
@ -275,14 +285,14 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
Il faut donc que tous les semestres 1...n-1 soient validés et que n+1 soit en attente.
|
Il faut donc que tous les semestres 1...n-1 soient validés et que n+1 soit en attente.
|
||||||
(et que le sem courant n soit validé, ce qui n'est pas testé ici)
|
(et que le sem courant n soit validé, ce qui n'est pas testé ici)
|
||||||
"""
|
"""
|
||||||
n = self.sem["semestre_id"]
|
s_idx = self.cur_sem.semestre_id
|
||||||
if not self.sem["gestion_semestrielle"]:
|
if not self.cur_sem.gestion_semestrielle:
|
||||||
return False # pas de semestre décalés
|
return False # pas de semestre décalés
|
||||||
if n == NO_SEMESTRE_ID or n > self.parcours.NB_SEM - 2:
|
if s_idx == NO_SEMESTRE_ID or s_idx > self.parcours.NB_SEM - 2:
|
||||||
return False # n+2 en dehors du parcours
|
return False # n+2 en dehors du parcours
|
||||||
if self._sem_list_validated(set(range(1, n))):
|
if self._sem_list_validated(set(range(1, s_idx))):
|
||||||
# antérieurs validé, teste suivant
|
# antérieurs validé, teste suivant
|
||||||
n1 = n + 1
|
n1 = s_idx + 1
|
||||||
for sem in self.get_semestres():
|
for sem in self.get_semestres():
|
||||||
if (
|
if (
|
||||||
sem["semestre_id"] == n1
|
sem["semestre_id"] == n1
|
||||||
@ -315,19 +325,17 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
return not sem_idx_set
|
return not sem_idx_set
|
||||||
|
|
||||||
def _comp_semestres(self):
|
def _comp_semestres(self):
|
||||||
# etud['sems'] est trie par date decroissante (voir fill_etuds_info)
|
# plus ancien en tête:
|
||||||
if not "sems" in self.etud:
|
self.formsemestres = self.etud.get_formsemestres(recent_first=False)
|
||||||
self.etud["sems"] = sco_etud.etud_inscriptions_infos(
|
|
||||||
self.etud["etudid"], self.etud["ne"]
|
|
||||||
)["sems"]
|
|
||||||
sems = self.etud["sems"][:] # copy
|
|
||||||
sems.reverse()
|
|
||||||
# Nb max d'UE et acronymes
|
# Nb max d'UE et acronymes
|
||||||
ue_acros = {} # acronyme ue : 1
|
ue_acros = {} # acronyme ue : 1
|
||||||
nb_max_ue = 0
|
nb_max_ue = 0
|
||||||
for sem in sems:
|
sems = []
|
||||||
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
for formsemestre in self.formsemestres: # plus ancien en tête
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
|
sem = formsemestre.to_dict()
|
||||||
|
sems.append(sem)
|
||||||
ues = nt.get_ues_stat_dict(filter_sport=True)
|
ues = nt.get_ues_stat_dict(filter_sport=True)
|
||||||
for ue in ues:
|
for ue in ues:
|
||||||
ue_acros[ue["acronyme"]] = 1
|
ue_acros[ue["acronyme"]] = 1
|
||||||
@ -338,14 +346,15 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
sem["formation_code"] = formsemestre.formation.formation_code
|
sem["formation_code"] = formsemestre.formation.formation_code
|
||||||
# si sem peut servir à compenser le semestre courant, positionne
|
# si sem peut servir à compenser le semestre courant, positionne
|
||||||
# can_compensate
|
# can_compensate
|
||||||
sem["can_compensate"] = self.check_compensation_dut(sem, nt)
|
if self.check_compensation_dut(sem, nt):
|
||||||
|
self.can_compensate.add(formsemestre.id)
|
||||||
|
|
||||||
self.ue_acros = list(ue_acros.keys())
|
self.ue_acros = list(ue_acros.keys())
|
||||||
self.ue_acros.sort()
|
self.ue_acros.sort()
|
||||||
self.nb_max_ue = nb_max_ue
|
self.nb_max_ue = nb_max_ue
|
||||||
self.sems = sems
|
self.sems = sems
|
||||||
|
|
||||||
def get_semestres(self):
|
def get_semestres(self) -> list[dict]:
|
||||||
"""Liste des semestres dans lesquels a été inscrit
|
"""Liste des semestres dans lesquels a été inscrit
|
||||||
l'étudiant (quelle que soit la formation), le plus ancien en tête"""
|
l'étudiant (quelle que soit la formation), le plus ancien en tête"""
|
||||||
return self.sems
|
return self.sems
|
||||||
@ -355,24 +364,30 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
Si filter_futur, ne mentionne pas les semestres qui sont après le semestre courant.
|
Si filter_futur, ne mentionne pas les semestres qui sont après le semestre courant.
|
||||||
Si filter_formation_code, restreint aux semestres de même code formation que le courant.
|
Si filter_formation_code, restreint aux semestres de même code formation que le courant.
|
||||||
"""
|
"""
|
||||||
cur_begin_date = self.sem["dateord"]
|
cur_begin_date = self.cur_sem.date_debut
|
||||||
cur_formation_code = self.sem["formation_code"]
|
cur_formation_code = self.cur_sem.formation.formation_code
|
||||||
p = []
|
p = []
|
||||||
for s in self.sems:
|
for formsemestre in self.formsemestres:
|
||||||
if s["ins"]["etat"] == scu.DEMISSION:
|
inscription = formsemestre.etuds_inscriptions.get(self.etud.id)
|
||||||
|
if inscription is None:
|
||||||
|
raise ValueError("Etudiant non inscrit au semestre") # bug
|
||||||
|
if inscription.etat == scu.DEMISSION:
|
||||||
dem = " (dem.)"
|
dem = " (dem.)"
|
||||||
else:
|
else:
|
||||||
dem = ""
|
dem = ""
|
||||||
if filter_futur and s["dateord"] > cur_begin_date:
|
if filter_futur and formsemestre.date_debut > cur_begin_date:
|
||||||
continue # skip semestres demarrant apres le courant
|
continue # skip semestres demarrant apres le courant
|
||||||
if filter_formation_code and s["formation_code"] != cur_formation_code:
|
if (
|
||||||
|
filter_formation_code
|
||||||
|
and formsemestre.formation.formation_code != cur_formation_code
|
||||||
|
):
|
||||||
continue # restreint aux semestres de la formation courante (pour les PV)
|
continue # restreint aux semestres de la formation courante (pour les PV)
|
||||||
session_abbrv = self.parcours.SESSION_ABBRV # 'S' ou 'A'
|
session_abbrv = self.parcours.SESSION_ABBRV # 'S' ou 'A'
|
||||||
if s["semestre_id"] < 0:
|
if formsemestre.semestre_id < 0:
|
||||||
session_abbrv = "A" # force, cas des DUT annuels par exemple
|
session_abbrv = "A" # force, cas des DUT annuels par exemple
|
||||||
p.append("%s%d%s" % (session_abbrv, -s["semestre_id"], dem))
|
p.append("%s%d%s" % (session_abbrv, -formsemestre.semestre_id, dem))
|
||||||
else:
|
else:
|
||||||
p.append("%s%d%s" % (session_abbrv, s["semestre_id"], dem))
|
p.append("%s%d%s" % (session_abbrv, formsemestre.semestre_id, dem))
|
||||||
return ", ".join(p)
|
return ", ".join(p)
|
||||||
|
|
||||||
def get_parcours_decisions(self):
|
def get_parcours_decisions(self):
|
||||||
@ -381,7 +396,7 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
Returns: { semestre_id : code }
|
Returns: { semestre_id : code }
|
||||||
"""
|
"""
|
||||||
r = {}
|
r = {}
|
||||||
if self.sem["semestre_id"] == NO_SEMESTRE_ID:
|
if self.cur_sem.semestre_id == NO_SEMESTRE_ID:
|
||||||
indices = [NO_SEMESTRE_ID]
|
indices = [NO_SEMESTRE_ID]
|
||||||
else:
|
else:
|
||||||
indices = list(range(1, self.parcours.NB_SEM + 1))
|
indices = list(range(1, self.parcours.NB_SEM + 1))
|
||||||
@ -424,22 +439,22 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
"true si ce semestre pourrait etre compensé par un autre (e.g. barres UE > 8)"
|
"true si ce semestre pourrait etre compensé par un autre (e.g. barres UE > 8)"
|
||||||
return self.barres_ue_ok
|
return self.barres_ue_ok
|
||||||
|
|
||||||
def _search_prev(self):
|
def _search_prev(self) -> FormSemestre | None:
|
||||||
"""Recherche semestre 'precedent'.
|
"""Recherche semestre 'precedent'.
|
||||||
return prev_formsemestre_id
|
positionne .prev_decision
|
||||||
"""
|
"""
|
||||||
self.prev = None
|
self.prev_formsemestre = None
|
||||||
self.prev_decision = None
|
self.prev_decision = None
|
||||||
if len(self.sems) < 2:
|
if len(self.formsemestres) < 2:
|
||||||
return None
|
return None
|
||||||
# Cherche sem courant dans la liste triee par date_debut
|
# Cherche sem courant dans la liste triee par date_debut
|
||||||
cur = None
|
cur = None
|
||||||
icur = -1
|
icur = -1
|
||||||
for cur in self.sems:
|
for cur in self.formsemestres:
|
||||||
icur += 1
|
icur += 1
|
||||||
if cur["formsemestre_id"] == self.formsemestre_id:
|
if cur.id == self.formsemestre_id:
|
||||||
break
|
break
|
||||||
if not cur or cur["formsemestre_id"] != self.formsemestre_id:
|
if not cur or cur.id != self.formsemestre_id:
|
||||||
log(
|
log(
|
||||||
f"*** SituationEtudCursus: search_prev: cur not found (formsemestre_id={self.formsemestre_id}, etudid={self.etudid})"
|
f"*** SituationEtudCursus: search_prev: cur not found (formsemestre_id={self.formsemestre_id}, etudid={self.etudid})"
|
||||||
)
|
)
|
||||||
@ -447,60 +462,59 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
# Cherche semestre antérieur de même formation (code) et semestre_id precedent
|
# Cherche semestre antérieur de même formation (code) et semestre_id precedent
|
||||||
#
|
#
|
||||||
# i = icur - 1 # part du courant, remonte vers le passé
|
# i = icur - 1 # part du courant, remonte vers le passé
|
||||||
i = len(self.sems) - 1 # par du dernier, remonte vers le passé
|
i = len(self.formsemestres) - 1 # par du dernier, remonte vers le passé
|
||||||
prev = None
|
prev_formsemestre = None
|
||||||
while i >= 0:
|
while i >= 0:
|
||||||
if (
|
if (
|
||||||
self.sems[i]["formation_code"] == self.formation.formation_code
|
self.formsemestres[i].formation.formation_code
|
||||||
and self.sems[i]["semestre_id"] == cur["semestre_id"] - 1
|
== self.formation.formation_code
|
||||||
|
and self.formsemestres[i].semestre_id == cur.semestre_id - 1
|
||||||
):
|
):
|
||||||
prev = self.sems[i]
|
prev_formsemestre = self.formsemestres[i]
|
||||||
break
|
break
|
||||||
i -= 1
|
i -= 1
|
||||||
if not prev:
|
if not prev_formsemestre:
|
||||||
return None # pas de precedent trouvé
|
return None # pas de precedent trouvé
|
||||||
self.prev = prev
|
self.prev_formsemestre = prev_formsemestre
|
||||||
# Verifications basiques:
|
# Verifications basiques:
|
||||||
# ?
|
# ?
|
||||||
# Code etat du semestre precedent:
|
# Code etat du semestre precedent:
|
||||||
formsemestre = FormSemestre.query.get_or_404(prev["formsemestre_id"])
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(prev_formsemestre)
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
|
||||||
self.prev_decision = nt.get_etud_decision_sem(self.etudid)
|
self.prev_decision = nt.get_etud_decision_sem(self.etudid)
|
||||||
self.prev_moy_gen = nt.get_etud_moy_gen(self.etudid)
|
self.prev_moy_gen = nt.get_etud_moy_gen(self.etudid)
|
||||||
self.prev_barres_ue_ok = nt.etud_check_conditions_ues(self.etudid)[0]
|
self.prev_barres_ue_ok = nt.etud_check_conditions_ues(self.etudid)[0]
|
||||||
return self.prev["formsemestre_id"]
|
|
||||||
|
|
||||||
def get_next_semestre_ids(self, devenir):
|
def get_next_semestre_ids(self, devenir: str) -> list[int]:
|
||||||
"""Liste des numeros de semestres autorises avec ce devenir
|
"""Liste des numeros de semestres autorises avec ce devenir
|
||||||
Ne vérifie pas que le devenir est possible (doit être fait avant),
|
Ne vérifie pas que le devenir est possible (doit être fait avant),
|
||||||
juste que le rang du semestre est dans le parcours [1..NB_SEM]
|
juste que le rang du semestre est dans le parcours [1..NB_SEM]
|
||||||
"""
|
"""
|
||||||
s = self.sem["semestre_id"]
|
s_idx = self.cur_sem.semestre_id
|
||||||
if devenir == NEXT:
|
if devenir == NEXT:
|
||||||
ids = [self._get_next_semestre_id()]
|
ids = [self._get_next_semestre_id()]
|
||||||
elif devenir == REDOANNEE:
|
elif devenir == REDOANNEE:
|
||||||
ids = [s - 1]
|
ids = [s_idx - 1]
|
||||||
elif devenir == REDOSEM:
|
elif devenir == REDOSEM:
|
||||||
ids = [s]
|
ids = [s_idx]
|
||||||
elif devenir == RA_OR_NEXT:
|
elif devenir == RA_OR_NEXT:
|
||||||
ids = [s - 1, self._get_next_semestre_id()]
|
ids = [s_idx - 1, self._get_next_semestre_id()]
|
||||||
elif devenir == RA_OR_RS:
|
elif devenir == RA_OR_RS:
|
||||||
ids = [s - 1, s]
|
ids = [s_idx - 1, s_idx]
|
||||||
elif devenir == RS_OR_NEXT:
|
elif devenir == RS_OR_NEXT:
|
||||||
ids = [s, self._get_next_semestre_id()]
|
ids = [s_idx, self._get_next_semestre_id()]
|
||||||
elif devenir == NEXT_OR_NEXT2:
|
elif devenir == NEXT_OR_NEXT2:
|
||||||
ids = [
|
ids = [
|
||||||
self._get_next_semestre_id(),
|
self._get_next_semestre_id(),
|
||||||
s + 2,
|
s_idx + 2,
|
||||||
] # cohérent avec explique_devenir()
|
] # cohérent avec explique_devenir()
|
||||||
elif devenir == NEXT2:
|
elif devenir == NEXT2:
|
||||||
ids = [s + 2]
|
ids = [s_idx + 2]
|
||||||
else:
|
else:
|
||||||
ids = [] # reoriente ou autre: pas de next !
|
ids = [] # reoriente ou autre: pas de next !
|
||||||
# clip [1..NB_SEM]
|
# clip [1..NB_SEM]
|
||||||
r = []
|
r = []
|
||||||
for idx in ids:
|
for idx in ids:
|
||||||
if idx > 0 and idx <= self.parcours.NB_SEM:
|
if 0 < idx <= self.parcours.NB_SEM:
|
||||||
r.append(idx)
|
r.append(idx)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@ -508,27 +522,27 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
"""Indice du semestre suivant non validé.
|
"""Indice du semestre suivant non validé.
|
||||||
S'il n'y en a pas, ramène NB_SEM+1
|
S'il n'y en a pas, ramène NB_SEM+1
|
||||||
"""
|
"""
|
||||||
s = self.sem["semestre_id"]
|
s_idx = self.cur_sem.semestre_id
|
||||||
if s >= self.parcours.NB_SEM:
|
if s_idx >= self.parcours.NB_SEM:
|
||||||
return self.parcours.NB_SEM + 1
|
return self.parcours.NB_SEM + 1
|
||||||
validated = True
|
validated = True
|
||||||
while validated and (s < self.parcours.NB_SEM):
|
while validated and (s_idx < self.parcours.NB_SEM):
|
||||||
s = s + 1
|
s_idx = s_idx + 1
|
||||||
# semestre s validé ?
|
# semestre s validé ?
|
||||||
validated = False
|
validated = False
|
||||||
for sem in self.sems:
|
for formsemestre in self.formsemestres:
|
||||||
if (
|
if (
|
||||||
sem["formation_code"] == self.formation.formation_code
|
formsemestre.formation.formation_code
|
||||||
and sem["semestre_id"] == s
|
== self.formation.formation_code
|
||||||
|
and formsemestre.semestre_id == s_idx
|
||||||
):
|
):
|
||||||
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(
|
||||||
formsemestre
|
formsemestre
|
||||||
)
|
)
|
||||||
decision = nt.get_etud_decision_sem(self.etudid)
|
decision = nt.get_etud_decision_sem(self.etudid)
|
||||||
if decision and code_semestre_validant(decision["code"]):
|
if decision and code_semestre_validant(decision["code"]):
|
||||||
validated = True
|
validated = True
|
||||||
return s
|
return s_idx
|
||||||
|
|
||||||
def valide_decision(self, decision):
|
def valide_decision(self, decision):
|
||||||
"""Enregistre la decision (instance de DecisionSem)
|
"""Enregistre la decision (instance de DecisionSem)
|
||||||
@ -543,8 +557,11 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
fsid = decision.formsemestre_id_utilise_pour_compenser
|
fsid = decision.formsemestre_id_utilise_pour_compenser
|
||||||
if fsid:
|
if fsid:
|
||||||
ok = False
|
ok = False
|
||||||
for sem in self.sems:
|
for formsemestre in self.formsemestres:
|
||||||
if sem["formsemestre_id"] == fsid and sem["can_compensate"]:
|
if (
|
||||||
|
formsemestre.id == fsid
|
||||||
|
and formsemestre.id in self.can_compensate
|
||||||
|
):
|
||||||
ok = True
|
ok = True
|
||||||
break
|
break
|
||||||
if not ok:
|
if not ok:
|
||||||
@ -585,7 +602,7 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
decision.assiduite,
|
decision.assiduite,
|
||||||
)
|
)
|
||||||
# -- modification du code du semestre precedent
|
# -- modification du code du semestre precedent
|
||||||
if self.prev and decision.new_code_prev:
|
if self.prev_formsemestre and decision.new_code_prev:
|
||||||
if decision.new_code_prev == ADC:
|
if decision.new_code_prev == ADC:
|
||||||
# ne compense le prec. qu'avec le sem. courant
|
# ne compense le prec. qu'avec le sem. courant
|
||||||
fsid = self.formsemestre_id
|
fsid = self.formsemestre_id
|
||||||
@ -593,7 +610,7 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
fsid = None
|
fsid = None
|
||||||
to_invalidate += formsemestre_update_validation_sem(
|
to_invalidate += formsemestre_update_validation_sem(
|
||||||
cnx,
|
cnx,
|
||||||
self.prev["formsemestre_id"],
|
self.prev_formsemestre.id,
|
||||||
self.etudid,
|
self.etudid,
|
||||||
decision.new_code_prev,
|
decision.new_code_prev,
|
||||||
assidu=True,
|
assidu=True,
|
||||||
@ -605,18 +622,18 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
etudid=self.etudid,
|
etudid=self.etudid,
|
||||||
commit=False,
|
commit=False,
|
||||||
msg="formsemestre_id=%s code=%s"
|
msg="formsemestre_id=%s code=%s"
|
||||||
% (self.prev["formsemestre_id"], decision.new_code_prev),
|
% (self.prev_formsemestre.id, decision.new_code_prev),
|
||||||
)
|
)
|
||||||
# modifs des codes d'UE (pourraient passer de ADM a CMP, meme sans modif des notes)
|
# modifs des codes d'UE (pourraient passer de ADM a CMP, meme sans modif des notes)
|
||||||
formsemestre_validate_ues(
|
formsemestre_validate_ues(
|
||||||
self.prev["formsemestre_id"],
|
self.prev_formsemestre.id,
|
||||||
self.etudid,
|
self.etudid,
|
||||||
decision.new_code_prev,
|
decision.new_code_prev,
|
||||||
decision.assiduite, # attention: en toute rigueur il faudrait utiliser une indication de l'assiduite au sem. precedent, que nous n'avons pas...
|
decision.assiduite, # attention: en toute rigueur il faudrait utiliser une indication de l'assiduite au sem. precedent, que nous n'avons pas...
|
||||||
)
|
)
|
||||||
|
|
||||||
sco_cache.invalidate_formsemestre(
|
sco_cache.invalidate_formsemestre(
|
||||||
formsemestre_id=self.prev["formsemestre_id"]
|
formsemestre_id=self.prev_formsemestre.id
|
||||||
) # > modif decisions jury (sem, UE)
|
) # > modif decisions jury (sem, UE)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -698,7 +715,7 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
class SituationEtudCursusECTS(SituationEtudCursusClassic):
|
class SituationEtudCursusECTS(SituationEtudCursusClassic):
|
||||||
"""Gestion parcours basés sur ECTS"""
|
"""Gestion parcours basés sur ECTS"""
|
||||||
|
|
||||||
def __init__(self, etud, formsemestre_id, nt):
|
def __init__(self, etud: Identite, formsemestre_id: int, nt):
|
||||||
SituationEtudCursusClassic.__init__(self, etud, formsemestre_id, nt)
|
SituationEtudCursusClassic.__init__(self, etud, formsemestre_id, nt)
|
||||||
|
|
||||||
def could_be_compensated(self):
|
def could_be_compensated(self):
|
||||||
|
@ -116,7 +116,7 @@ def formsemestre_validation_etud_form(
|
|||||||
check = True
|
check = True
|
||||||
|
|
||||||
etud_d = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud_d = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud_d, formsemestre_id)
|
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
||||||
if not Se.sem["etat"]:
|
if not Se.sem["etat"]:
|
||||||
raise ScoValueError("validation: semestre verrouille")
|
raise ScoValueError("validation: semestre verrouille")
|
||||||
|
|
||||||
@ -262,8 +262,8 @@ def formsemestre_validation_etud_form(
|
|||||||
return "\n".join(H + footer)
|
return "\n".join(H + footer)
|
||||||
|
|
||||||
# Infos si pas de semestre précédent
|
# Infos si pas de semestre précédent
|
||||||
if not Se.prev:
|
if not Se.prev_formsemestre:
|
||||||
if Se.sem["semestre_id"] == 1:
|
if Se.cur_sem.semestre_id == 1:
|
||||||
H.append("<p>Premier semestre (pas de précédent)</p>")
|
H.append("<p>Premier semestre (pas de précédent)</p>")
|
||||||
else:
|
else:
|
||||||
H.append("<p>Pas de semestre précédent !</p>")
|
H.append("<p>Pas de semestre précédent !</p>")
|
||||||
@ -274,7 +274,7 @@ def formsemestre_validation_etud_form(
|
|||||||
f"""Le jury n'a pas statué sur le semestre précédent ! (<a href="{
|
f"""Le jury n'a pas statué sur le semestre précédent ! (<a href="{
|
||||||
url_for("notes.formsemestre_validation_etud_form",
|
url_for("notes.formsemestre_validation_etud_form",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
formsemestre_id=Se.prev["formsemestre_id"],
|
formsemestre_id=Se.prev_formsemestre.id,
|
||||||
etudid=etudid)
|
etudid=etudid)
|
||||||
}">le faire maintenant</a>)
|
}">le faire maintenant</a>)
|
||||||
"""
|
"""
|
||||||
@ -310,9 +310,9 @@ def formsemestre_validation_etud_form(
|
|||||||
H.append("</p>")
|
H.append("</p>")
|
||||||
|
|
||||||
# Cas particulier pour ATJ: corriger precedent avant de continuer
|
# Cas particulier pour ATJ: corriger precedent avant de continuer
|
||||||
if Se.prev_decision and Se.prev_decision["code"] == ATJ:
|
if Se.prev_formsemestre and Se.prev_decision and Se.prev_decision["code"] == ATJ:
|
||||||
H.append(
|
H.append(
|
||||||
"""<div class="sfv_warning"><p>La décision du semestre précédent est en
|
f"""<div class="sfv_warning"><p>La décision du semestre précédent est en
|
||||||
<b>attente</b> à cause d\'un <b>problème d\'assiduité<b>.</p>
|
<b>attente</b> à cause d\'un <b>problème d\'assiduité<b>.</p>
|
||||||
<p>Vous devez la corriger avant de continuer ce jury. Soit vous considérez que le
|
<p>Vous devez la corriger avant de continuer ce jury. Soit vous considérez que le
|
||||||
problème d'assiduité n'est pas réglé et choisissez de ne pas valider le semestre
|
problème d'assiduité n'est pas réglé et choisissez de ne pas valider le semestre
|
||||||
@ -320,14 +320,16 @@ def formsemestre_validation_etud_form(
|
|||||||
l'assiduité.</p>
|
l'assiduité.</p>
|
||||||
<form method="get" action="formsemestre_validation_etud_form">
|
<form method="get" action="formsemestre_validation_etud_form">
|
||||||
<input type="submit" value="Statuer sur le semestre précédent"/>
|
<input type="submit" value="Statuer sur le semestre précédent"/>
|
||||||
<input type="hidden" name="formsemestre_id" value="%s"/>
|
<input type="hidden" name="formsemestre_id" value="{Se.prev_formsemestre.id}"/>
|
||||||
<input type="hidden" name="etudid" value="%s"/>
|
<input type="hidden" name="etudid" value="{etudid}"/>
|
||||||
<input type="hidden" name="desturl" value="formsemestre_validation_etud_form?etudid=%s&formsemestre_id=%s"/>
|
<input type="hidden" name="desturl" value="{
|
||||||
|
url_for("notes.formsemestre_validation_etud_form",
|
||||||
|
etudid=etudid, formsemestre_id=formsemestre_id, scodoc_dept=g.scodoc_dept
|
||||||
|
)}"/>
|
||||||
"""
|
"""
|
||||||
% (Se.prev["formsemestre_id"], etudid, etudid, formsemestre_id)
|
|
||||||
)
|
)
|
||||||
if sortcol:
|
if sortcol:
|
||||||
H.append('<input type="hidden" name="sortcol" value="%s"/>' % sortcol)
|
H.append(f"""<input type="hidden" name="sortcol" value="{sortcol}"/>""")
|
||||||
H.append("</form></div>")
|
H.append("</form></div>")
|
||||||
|
|
||||||
H.append(html_sco_header.sco_footer())
|
H.append(html_sco_header.sco_footer())
|
||||||
@ -405,7 +407,7 @@ def formsemestre_validation_etud(
|
|||||||
sortcol=None,
|
sortcol=None,
|
||||||
):
|
):
|
||||||
"""Enregistre validation"""
|
"""Enregistre validation"""
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud = Identite.get_etud(etudid)
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
||||||
# retrouve la decision correspondant au code:
|
# retrouve la decision correspondant au code:
|
||||||
choices = Se.get_possible_choices(assiduite=True)
|
choices = Se.get_possible_choices(assiduite=True)
|
||||||
@ -438,7 +440,7 @@ def formsemestre_validation_etud_manu(
|
|||||||
"""Enregistre validation"""
|
"""Enregistre validation"""
|
||||||
if assidu:
|
if assidu:
|
||||||
assidu = True
|
assidu = True
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud = Identite.get_etud(etudid)
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
||||||
if code_etat in Se.parcours.UNUSED_CODES:
|
if code_etat in Se.parcours.UNUSED_CODES:
|
||||||
raise ScoValueError("code decision invalide dans ce parcours")
|
raise ScoValueError("code decision invalide dans ce parcours")
|
||||||
@ -494,32 +496,35 @@ def decisions_possible_rows(Se, assiduite, subtitle="", trclass=""):
|
|||||||
choices = Se.get_possible_choices(assiduite=assiduite)
|
choices = Se.get_possible_choices(assiduite=assiduite)
|
||||||
if not choices:
|
if not choices:
|
||||||
return ""
|
return ""
|
||||||
TitlePrev = ""
|
prev_title = ""
|
||||||
if Se.prev:
|
if Se.prev_formsemestre:
|
||||||
if Se.prev["semestre_id"] >= 0:
|
if Se.prev_formsemestre.semestre_id >= 0:
|
||||||
TitlePrev = "%s%d" % (Se.parcours.SESSION_ABBRV, Se.prev["semestre_id"])
|
prev_title = "%s%d" % (
|
||||||
|
Se.parcours.SESSION_ABBRV,
|
||||||
|
Se.prev_formsemestre.semestre_id,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
TitlePrev = "Prec."
|
prev_title = "Prec."
|
||||||
|
|
||||||
if Se.sem["semestre_id"] >= 0:
|
if Se.cur_sem.semestre_id >= 0:
|
||||||
TitleCur = "%s%d" % (Se.parcours.SESSION_ABBRV, Se.sem["semestre_id"])
|
cur_title = "%s%d" % (Se.parcours.SESSION_ABBRV, Se.cur_sem.semestre_id)
|
||||||
else:
|
else:
|
||||||
TitleCur = Se.parcours.SESSION_NAME
|
cur_title = Se.parcours.SESSION_NAME
|
||||||
|
|
||||||
H = [
|
H = [
|
||||||
'<tr class="%s titles"><th class="sfv_subtitle">%s</em></th>'
|
'<tr class="%s titles"><th class="sfv_subtitle">%s</em></th>'
|
||||||
% (trclass, subtitle)
|
% (trclass, subtitle)
|
||||||
]
|
]
|
||||||
if Se.prev:
|
if Se.prev_formsemestre:
|
||||||
H.append("<th>Code %s</th>" % TitlePrev)
|
H.append(f"<th>Code {prev_title}</th>")
|
||||||
H.append("<th>Code %s</th><th>Devenir</th></tr>" % TitleCur)
|
H.append(f"<th>Code {cur_title}</th><th>Devenir</th></tr>")
|
||||||
for ch in choices:
|
for ch in choices:
|
||||||
H.append(
|
H.append(
|
||||||
"""<tr class="%s"><td title="règle %s"><input type="radio" name="codechoice" value="%s" onClick="document.getElementById('subut').disabled=false;">"""
|
"""<tr class="%s"><td title="règle %s"><input type="radio" name="codechoice" value="%s" onClick="document.getElementById('subut').disabled=false;">"""
|
||||||
% (trclass, ch.rule_id, ch.codechoice)
|
% (trclass, ch.rule_id, ch.codechoice)
|
||||||
)
|
)
|
||||||
H.append("%s </input></td>" % ch.explication)
|
H.append("%s </input></td>" % ch.explication)
|
||||||
if Se.prev:
|
if Se.prev_formsemestre:
|
||||||
H.append('<td class="centercell">%s</td>' % _dispcode(ch.new_code_prev))
|
H.append('<td class="centercell">%s</td>' % _dispcode(ch.new_code_prev))
|
||||||
H.append(
|
H.append(
|
||||||
'<td class="centercell">%s</td><td>%s</td>'
|
'<td class="centercell">%s</td><td>%s</td>'
|
||||||
@ -535,7 +540,6 @@ def formsemestre_recap_parcours_table(
|
|||||||
etudid,
|
etudid,
|
||||||
with_links=False,
|
with_links=False,
|
||||||
with_all_columns=True,
|
with_all_columns=True,
|
||||||
a_url="",
|
|
||||||
sem_info=None,
|
sem_info=None,
|
||||||
show_details=False,
|
show_details=False,
|
||||||
):
|
):
|
||||||
@ -576,14 +580,14 @@ def formsemestre_recap_parcours_table(
|
|||||||
H.append("<th></th></tr>")
|
H.append("<th></th></tr>")
|
||||||
|
|
||||||
num_sem = 0
|
num_sem = 0
|
||||||
for sem in situation_etud_cursus.get_semestres():
|
for formsemestre in situation_etud_cursus.formsemestres:
|
||||||
is_prev = situation_etud_cursus.prev and (
|
is_prev = situation_etud_cursus.prev_formsemestre and (
|
||||||
situation_etud_cursus.prev["formsemestre_id"] == sem["formsemestre_id"]
|
situation_etud_cursus.prev_formsemestre.id == formsemestre.id
|
||||||
)
|
)
|
||||||
is_cur = situation_etud_cursus.formsemestre_id == sem["formsemestre_id"]
|
is_cur = situation_etud_cursus.formsemestre_id == formsemestre.id
|
||||||
num_sem += 1
|
num_sem += 1
|
||||||
|
|
||||||
dpv = sco_pv_dict.dict_pvjury(sem["formsemestre_id"], etudids=[etudid])
|
dpv = sco_pv_dict.dict_pvjury(formsemestre.id, etudids=[etudid])
|
||||||
pv = dpv["decisions"][0]
|
pv = dpv["decisions"][0]
|
||||||
decision_sem = pv["decision_sem"]
|
decision_sem = pv["decision_sem"]
|
||||||
decisions_ue = pv["decisions_ue"]
|
decisions_ue = pv["decisions_ue"]
|
||||||
@ -592,7 +596,6 @@ def formsemestre_recap_parcours_table(
|
|||||||
else:
|
else:
|
||||||
ass = ""
|
ass = ""
|
||||||
|
|
||||||
formsemestre = db.session.get(FormSemestre, sem["formsemestre_id"])
|
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
if is_cur:
|
if is_cur:
|
||||||
type_sem = "*" # now unused
|
type_sem = "*" # now unused
|
||||||
@ -603,20 +606,24 @@ def formsemestre_recap_parcours_table(
|
|||||||
else:
|
else:
|
||||||
type_sem = ""
|
type_sem = ""
|
||||||
class_sem = "sem_autre"
|
class_sem = "sem_autre"
|
||||||
if sem["formation_code"] != situation_etud_cursus.formation.formation_code:
|
if (
|
||||||
|
formsemestre.formation.formation_code
|
||||||
|
!= situation_etud_cursus.formation.formation_code
|
||||||
|
):
|
||||||
class_sem += " sem_autre_formation"
|
class_sem += " sem_autre_formation"
|
||||||
if sem["bul_bgcolor"]:
|
bgcolor = (
|
||||||
bgcolor = sem["bul_bgcolor"]
|
formsemestre.bul_bgcolor
|
||||||
else:
|
if formsemestre.bul_bgcolor
|
||||||
bgcolor = "background-color: rgb(255,255,240)"
|
else "background-color: rgb(255,255,240)"
|
||||||
|
)
|
||||||
# 1ere ligne: titre sem, decision, acronymes UE
|
# 1ere ligne: titre sem, decision, acronymes UE
|
||||||
H.append('<tr class="%s rcp_l1 sem_%s">' % (class_sem, sem["formsemestre_id"]))
|
H.append('<tr class="%s rcp_l1 sem_%s">' % (class_sem, formsemestre.id))
|
||||||
if is_cur:
|
if is_cur:
|
||||||
pm = ""
|
pm = ""
|
||||||
elif is_prev:
|
elif is_prev:
|
||||||
pm = minuslink % sem["formsemestre_id"]
|
pm = minuslink % formsemestre.id
|
||||||
else:
|
else:
|
||||||
pm = plusminus % sem["formsemestre_id"]
|
pm = plusminus % formsemestre.id
|
||||||
|
|
||||||
inscr = formsemestre.etuds_inscriptions.get(etudid)
|
inscr = formsemestre.etuds_inscriptions.get(etudid)
|
||||||
parcours_name = ""
|
parcours_name = ""
|
||||||
@ -638,9 +645,12 @@ def formsemestre_recap_parcours_table(
|
|||||||
H.append(
|
H.append(
|
||||||
f"""
|
f"""
|
||||||
<td class="rcp_type_sem" style="background-color:{bgcolor};">{num_sem}{pm}</td>
|
<td class="rcp_type_sem" style="background-color:{bgcolor};">{num_sem}{pm}</td>
|
||||||
<td class="datedebut">{sem['mois_debut']}</td>
|
<td class="datedebut">{formsemestre.mois_debut()}</td>
|
||||||
<td class="rcp_titre_sem"><a class="formsemestre_status_link"
|
<td class="rcp_titre_sem"><a class="formsemestre_status_link"
|
||||||
href="{a_url}formsemestre_bulletinetud?formsemestre_id={formsemestre.id}&etudid={etudid}"
|
href="{
|
||||||
|
url_for("notes.formsemestre_bulletinetud", scodoc_dept=g.scodoc_dept,
|
||||||
|
formsemestre_id=formsemestre.id, etudid=etudid
|
||||||
|
)}"
|
||||||
title="Bulletin de notes">{formsemestre.titre_annee()}{parcours_name}</a>
|
title="Bulletin de notes">{formsemestre.titre_annee()}{parcours_name}</a>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@ -675,7 +685,7 @@ def formsemestre_recap_parcours_table(
|
|||||||
ues = [
|
ues = [
|
||||||
ue
|
ue
|
||||||
for ue in ues
|
for ue in ues
|
||||||
if etud_est_inscrit_ue(cnx, etudid, sem["formsemestre_id"], ue.id)
|
if etud_est_inscrit_ue(cnx, etudid, formsemestre.id, ue.id)
|
||||||
or etud_ue_status[ue.id]["is_capitalized"]
|
or etud_ue_status[ue.id]["is_capitalized"]
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -697,7 +707,7 @@ def formsemestre_recap_parcours_table(
|
|||||||
H.append("<td></td>")
|
H.append("<td></td>")
|
||||||
H.append("</tr>")
|
H.append("</tr>")
|
||||||
# 2eme ligne: notes
|
# 2eme ligne: notes
|
||||||
H.append(f"""<tr class="{class_sem} rcp_l2 sem_{sem["formsemestre_id"]}">""")
|
H.append(f"""<tr class="{class_sem} rcp_l2 sem_{formsemestre.id}">""")
|
||||||
H.append(
|
H.append(
|
||||||
f"""<td class="rcp_type_sem"
|
f"""<td class="rcp_type_sem"
|
||||||
style="background-color:{bgcolor};"> </td>"""
|
style="background-color:{bgcolor};"> </td>"""
|
||||||
@ -706,21 +716,28 @@ def formsemestre_recap_parcours_table(
|
|||||||
default_sem_info = '<span class="fontred">[sem. précédent]</span>'
|
default_sem_info = '<span class="fontred">[sem. précédent]</span>'
|
||||||
else:
|
else:
|
||||||
default_sem_info = ""
|
default_sem_info = ""
|
||||||
if not sem["etat"]: # locked
|
if not formsemestre.etat: # locked
|
||||||
lockicon = scu.icontag("lock32_img", title="verrouillé", border="0")
|
lockicon = scu.icontag("lock32_img", title="verrouillé", border="0")
|
||||||
default_sem_info += lockicon
|
default_sem_info += lockicon
|
||||||
if sem["formation_code"] != situation_etud_cursus.formation.formation_code:
|
if (
|
||||||
default_sem_info += f"""Autre formation: {sem["formation_code"]}"""
|
formsemestre.formation.formation_code
|
||||||
|
!= situation_etud_cursus.formation.formation_code
|
||||||
|
):
|
||||||
|
default_sem_info += (
|
||||||
|
f"""Autre formation: {formsemestre.formation.formation_code}"""
|
||||||
|
)
|
||||||
H.append(
|
H.append(
|
||||||
'<td class="datefin">%s</td><td class="sem_info">%s</td>'
|
'<td class="datefin">%s</td><td class="sem_info">%s</td>'
|
||||||
% (sem["mois_fin"], sem_info.get(sem["formsemestre_id"], default_sem_info))
|
% (formsemestre.mois_fin(), sem_info.get(formsemestre.id, default_sem_info))
|
||||||
)
|
)
|
||||||
# Moy Gen (sous le code decision)
|
# Moy Gen (sous le code decision)
|
||||||
H.append(
|
H.append(
|
||||||
f"""<td class="rcp_moy">{scu.fmt_note(nt.get_etud_moy_gen(etudid))}</td>"""
|
f"""<td class="rcp_moy">{scu.fmt_note(nt.get_etud_moy_gen(etudid))}</td>"""
|
||||||
)
|
)
|
||||||
# Absences (nb d'abs non just. dans ce semestre)
|
# Absences (nb d'abs non just. dans ce semestre)
|
||||||
nbabsnj = sco_assiduites.get_assiduites_count(etudid, sem)[0]
|
nbabsnj = sco_assiduites.formsemestre_get_assiduites_count(
|
||||||
|
etudid, formsemestre
|
||||||
|
)[0]
|
||||||
H.append(f"""<td class="rcp_abs">{nbabsnj}</td>""")
|
H.append(f"""<td class="rcp_abs">{nbabsnj}</td>""")
|
||||||
|
|
||||||
# UEs
|
# UEs
|
||||||
@ -767,26 +784,30 @@ def formsemestre_recap_parcours_table(
|
|||||||
H.append("<td></td>")
|
H.append("<td></td>")
|
||||||
if with_links:
|
if with_links:
|
||||||
H.append(
|
H.append(
|
||||||
'<td><a href="%sformsemestre_validation_etud_form?formsemestre_id=%s&etudid=%s">modifier</a></td>'
|
f"""<td><a class="stdlink" href="{
|
||||||
% (a_url, sem["formsemestre_id"], etudid)
|
url_for("notes.formsemestre_validation_etud_form", scodoc_dept=g.scodoc_dept,
|
||||||
|
formsemestre_id=formsemestre.id, etudid=etudid
|
||||||
|
)}">modifier</a></td>"""
|
||||||
)
|
)
|
||||||
|
|
||||||
H.append("</tr>")
|
H.append("</tr>")
|
||||||
# 3eme ligne: ECTS
|
# 3eme ligne: ECTS
|
||||||
if (
|
if (
|
||||||
sco_preferences.get_preference("bul_show_ects", sem["formsemestre_id"])
|
sco_preferences.get_preference("bul_show_ects", formsemestre.id)
|
||||||
or nt.parcours.ECTS_ONLY
|
or nt.parcours.ECTS_ONLY
|
||||||
):
|
):
|
||||||
etud_ects_infos = nt.get_etud_ects_pot(etudid) # ECTS potentiels
|
etud_ects_infos = nt.get_etud_ects_pot(etudid) # ECTS potentiels
|
||||||
H.append(
|
H.append(
|
||||||
f"""<tr class="{class_sem} rcp_l2 sem_{sem["formsemestre_id"]}">
|
f"""<tr class="{class_sem} rcp_l2 sem_{formsemestre.id}">
|
||||||
<td class="rcp_type_sem" style="background-color:{bgcolor};"> </td>
|
<td class="rcp_type_sem" style="background-color:{bgcolor};"> </td>
|
||||||
<td></td>"""
|
<td></td>"""
|
||||||
)
|
)
|
||||||
# Total ECTS (affiché sous la moyenne générale)
|
# Total ECTS (affiché sous la moyenne générale)
|
||||||
H.append(
|
H.append(
|
||||||
f"""<td class="sem_ects_tit"><a title="crédit acquis">ECTS:</a></td>
|
f"""<td class="sem_ects_tit"><a title="crédit acquis">ECTS:</a></td>
|
||||||
<td class="sem_ects">{pv.get("sum_ects",0):2.2g} / {etud_ects_infos["ects_total"]:2.2g}</td>
|
<td class="sem_ects">{
|
||||||
|
pv.get("sum_ects",0):2.2g} / {etud_ects_infos["ects_total"]:2.2g
|
||||||
|
}</td>
|
||||||
<td class="rcp_abs"></td>
|
<td class="rcp_abs"></td>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@ -865,7 +886,7 @@ def form_decision_manuelle(Se, formsemestre_id, etudid, desturl="", sortcol=None
|
|||||||
# précédent n'est pas géré dans ScoDoc (code ADC_)
|
# précédent n'est pas géré dans ScoDoc (code ADC_)
|
||||||
# log(str(Se.sems))
|
# log(str(Se.sems))
|
||||||
for sem in Se.sems:
|
for sem in Se.sems:
|
||||||
if sem["can_compensate"]:
|
if sem["formsemestre_id"] in Se.can_compensate:
|
||||||
H.append(
|
H.append(
|
||||||
'<option value="%s_%s">Admis par compensation avec S%s (%s)</option>'
|
'<option value="%s_%s">Admis par compensation avec S%s (%s)</option>'
|
||||||
% (
|
% (
|
||||||
@ -882,7 +903,7 @@ def form_decision_manuelle(Se, formsemestre_id, etudid, desturl="", sortcol=None
|
|||||||
H.append("</select></td></tr>")
|
H.append("</select></td></tr>")
|
||||||
|
|
||||||
# Choix code semestre precedent:
|
# Choix code semestre precedent:
|
||||||
if Se.prev:
|
if Se.prev_formsemestre:
|
||||||
H.append(
|
H.append(
|
||||||
'<tr><td>Code semestre précédent: </td><td><select name="new_code_prev"><option value="">Choisir une décision...</option>'
|
'<tr><td>Code semestre précédent: </td><td><select name="new_code_prev"><option value="">Choisir une décision...</option>'
|
||||||
)
|
)
|
||||||
@ -975,7 +996,7 @@ def do_formsemestre_validation_auto(formsemestre_id):
|
|||||||
conflicts = [] # liste des etudiants avec decision differente déjà saisie
|
conflicts = [] # liste des etudiants avec decision differente déjà saisie
|
||||||
with sco_cache.DeferredSemCacheManager():
|
with sco_cache.DeferredSemCacheManager():
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
etud = Identite.get_etud(etudid)
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
||||||
ins = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
|
ins = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
|
||||||
{"etudid": etudid, "formsemestre_id": formsemestre_id}
|
{"etudid": etudid, "formsemestre_id": formsemestre_id}
|
||||||
@ -984,7 +1005,7 @@ def do_formsemestre_validation_auto(formsemestre_id):
|
|||||||
# Conditions pour validation automatique:
|
# Conditions pour validation automatique:
|
||||||
if ins["etat"] == scu.INSCRIT and (
|
if ins["etat"] == scu.INSCRIT and (
|
||||||
(
|
(
|
||||||
(not Se.prev)
|
(not Se.prev_formsemestre)
|
||||||
or (
|
or (
|
||||||
Se.prev_decision and Se.prev_decision["code"] in (ADM, ADC, ADJ)
|
Se.prev_decision and Se.prev_decision["code"] in (ADM, ADC, ADJ)
|
||||||
)
|
)
|
||||||
@ -1055,8 +1076,8 @@ def do_formsemestre_validation_auto(formsemestre_id):
|
|||||||
f"""<li><a href="{
|
f"""<li><a href="{
|
||||||
url_for('notes.formsemestre_validation_etud_form',
|
url_for('notes.formsemestre_validation_etud_form',
|
||||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id,
|
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id,
|
||||||
etudid=etud["etudid"], check=1)
|
etudid=etud.id, check=1)
|
||||||
}">{etud["nomprenom"]}</li>"""
|
}">{etud_d["nomprenom"]}</li>"""
|
||||||
)
|
)
|
||||||
H.append("</ul>")
|
H.append("</ul>")
|
||||||
H.append(
|
H.append(
|
||||||
|
@ -466,9 +466,9 @@ def etud_add_group_infos(
|
|||||||
etud['groupes'] = "TDB, Gr2, TPB1"
|
etud['groupes'] = "TDB, Gr2, TPB1"
|
||||||
etud['partitionsgroupes'] = "Groupes TD:TDB, Groupes TP:Gr2 (...)"
|
etud['partitionsgroupes'] = "Groupes TD:TDB, Groupes TP:Gr2 (...)"
|
||||||
"""
|
"""
|
||||||
etud[
|
etud["partitions"] = (
|
||||||
"partitions"
|
collections.OrderedDict()
|
||||||
] = collections.OrderedDict() # partition_id : group + partition_name
|
) # partition_id : group + partition_name
|
||||||
if not formsemestre_id:
|
if not formsemestre_id:
|
||||||
etud["groupes"] = ""
|
etud["groupes"] = ""
|
||||||
return etud
|
return etud
|
||||||
@ -1409,21 +1409,17 @@ def groups_auto_repartition(partition: Partition):
|
|||||||
return flask.redirect(dest_url)
|
return flask.redirect(dest_url)
|
||||||
|
|
||||||
|
|
||||||
def _get_prev_moy(etudid, formsemestre_id):
|
def _get_prev_moy(etudid: int, formsemestre_id: int) -> float | str:
|
||||||
"""Donne la derniere moyenne generale calculee pour cette étudiant,
|
"""Donne la derniere moyenne generale calculee pour cette étudiant,
|
||||||
ou 0 si on n'en trouve pas (nouvel inscrit,...).
|
ou 0 si on n'en trouve pas (nouvel inscrit,...).
|
||||||
"""
|
"""
|
||||||
info = sco_etud.get_etud_info(etudid=etudid, filled=True)
|
etud = Identite.get_etud(etudid)
|
||||||
if not info:
|
|
||||||
raise ScoValueError("etudiant invalide: etudid=%s" % etudid)
|
|
||||||
etud = info[0]
|
|
||||||
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
||||||
if Se.prev:
|
if Se.prev_formsemestre:
|
||||||
prev_sem = db.session.get(FormSemestre, Se.prev["formsemestre_id"])
|
prev_sem = db.session.get(FormSemestre, Se.prev_formsemestre.id)
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(prev_sem)
|
nt: NotesTableCompat = res_sem.load_formsemestre_results(prev_sem)
|
||||||
return nt.get_etud_moy_gen(etudid)
|
return nt.get_etud_moy_gen(etud.id)
|
||||||
else:
|
return 0.0
|
||||||
return 0.0
|
|
||||||
|
|
||||||
|
|
||||||
def create_etapes_partition(formsemestre_id, partition_name="apo_etapes"):
|
def create_etapes_partition(formsemestre_id, partition_name="apo_etapes"):
|
||||||
|
@ -27,10 +27,8 @@
|
|||||||
|
|
||||||
"""Exports groupes
|
"""Exports groupes
|
||||||
"""
|
"""
|
||||||
from flask import request
|
|
||||||
|
|
||||||
from app.scodoc import notesdb as ndb
|
from app.scodoc import notesdb as ndb
|
||||||
from app.scodoc import sco_excel
|
|
||||||
from app.scodoc import sco_groups_view
|
from app.scodoc import sco_groups_view
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
@ -83,9 +81,7 @@ def groups_export_annotations(group_ids, formsemestre_id=None, fmt="html"):
|
|||||||
"date_str": "Date",
|
"date_str": "Date",
|
||||||
"comment": "Annotation",
|
"comment": "Annotation",
|
||||||
},
|
},
|
||||||
origin="Généré par %s le " % sco_version.SCONAME
|
origin=f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}",
|
||||||
+ scu.timedate_human_repr()
|
|
||||||
+ "",
|
|
||||||
page_title=f"Annotations sur les étudiants de {groups_infos.groups_titles}",
|
page_title=f"Annotations sur les étudiants de {groups_infos.groups_titles}",
|
||||||
caption="Annotations",
|
caption="Annotations",
|
||||||
base_url=groups_infos.base_url,
|
base_url=groups_infos.base_url,
|
||||||
|
@ -39,7 +39,7 @@ from flask import url_for, g, request
|
|||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre, Identite
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_excel
|
from app.scodoc import sco_excel
|
||||||
@ -585,8 +585,8 @@ def groups_table(
|
|||||||
etud_info["_nom_disp_order"] = etud_sort_key(etud_info)
|
etud_info["_nom_disp_order"] = etud_sort_key(etud_info)
|
||||||
etud_info["_prenom_target"] = fiche_url
|
etud_info["_prenom_target"] = fiche_url
|
||||||
|
|
||||||
etud_info["_nom_disp_td_attrs"] = (
|
etud_info["_nom_disp_td_attrs"] = 'id="%s" class="etudinfo"' % (
|
||||||
'id="%s" class="etudinfo"' % (etud_info["etudid"])
|
etud_info["etudid"]
|
||||||
)
|
)
|
||||||
etud_info["bourse_str"] = "oui" if etud_info["boursier"] else "non"
|
etud_info["bourse_str"] = "oui" if etud_info["boursier"] else "non"
|
||||||
if etud_info["etat"] == "D":
|
if etud_info["etat"] == "D":
|
||||||
@ -862,21 +862,25 @@ def groups_table(
|
|||||||
# et ajoute infos inscription
|
# et ajoute infos inscription
|
||||||
for m in groups_infos.members:
|
for m in groups_infos.members:
|
||||||
etud_info = sco_etud.get_etud_info(m["etudid"], filled=True)[0]
|
etud_info = sco_etud.get_etud_info(m["etudid"], filled=True)[0]
|
||||||
|
# TODO utiliser Identite
|
||||||
|
etud = Identite.get_etud(m["etudid"])
|
||||||
m.update(etud_info)
|
m.update(etud_info)
|
||||||
sco_etud.etud_add_lycee_infos(etud_info)
|
sco_etud.etud_add_lycee_infos(etud_info)
|
||||||
# et ajoute le parcours
|
# et ajoute le parcours
|
||||||
Se = sco_cursus.get_situation_etud_cursus(
|
Se = sco_cursus.get_situation_etud_cursus(
|
||||||
etud_info, groups_infos.formsemestre_id
|
etud, groups_infos.formsemestre_id
|
||||||
)
|
)
|
||||||
m["parcours"] = Se.get_cursus_descr()
|
m["parcours"] = Se.get_cursus_descr()
|
||||||
m["code_cursus"], _ = sco_report.get_code_cursus_etud(
|
m["code_cursus"], _ = sco_report.get_code_cursus_etud(
|
||||||
etud_info["etudid"], sems=etud_info["sems"]
|
etud.id, formsemestres=etud.get_formsemestres()
|
||||||
)
|
)
|
||||||
|
# TODO utiliser Identite:
|
||||||
rows = [[m.get(k, "") for k in keys] for m in groups_infos.members]
|
rows = [[m.get(k, "") for k in keys] for m in groups_infos.members]
|
||||||
title = "etudiants_%s" % groups_infos.groups_filename
|
title = f"etudiants_{groups_infos.groups_filename}"
|
||||||
xls = sco_excel.excel_simple_table(titles=titles, lines=rows, sheet_name=title)
|
xls = sco_excel.excel_simple_table(titles=titles, lines=rows, sheet_name=title)
|
||||||
filename = title
|
return scu.send_file(
|
||||||
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE)
|
xls, filename=title, suffix=scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise ScoValueError("unsupported format")
|
raise ScoValueError("unsupported format")
|
||||||
|
|
||||||
|
@ -264,14 +264,13 @@ def fiche_etud(etudid=None):
|
|||||||
sem_info[formsemestre.id] = grlink
|
sem_info[formsemestre.id] = grlink
|
||||||
|
|
||||||
if inscriptions:
|
if inscriptions:
|
||||||
Se = sco_cursus.get_situation_etud_cursus(info, info["last_formsemestre_id"])
|
Se = sco_cursus.get_situation_etud_cursus(etud, info["last_formsemestre_id"])
|
||||||
info["liste_inscriptions"] = formsemestre_recap_parcours_table(
|
info["liste_inscriptions"] = formsemestre_recap_parcours_table(
|
||||||
Se,
|
Se,
|
||||||
etudid,
|
etudid,
|
||||||
with_links=False,
|
with_links=False,
|
||||||
sem_info=sem_info,
|
sem_info=sem_info,
|
||||||
with_all_columns=False,
|
with_all_columns=False,
|
||||||
a_url="Notes/",
|
|
||||||
)
|
)
|
||||||
info["link_bul_pdf"] = (
|
info["link_bul_pdf"] = (
|
||||||
"""<span class="link_bul_pdf fontred">PDF interdits par l'admin.</span>"""
|
"""<span class="link_bul_pdf fontred">PDF interdits par l'admin.</span>"""
|
||||||
|
@ -81,14 +81,11 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
nbabs = {}
|
nbabs = {}
|
||||||
nbabsjust = {}
|
nbabsjust = {}
|
||||||
for etud in etuds:
|
for etud in etuds:
|
||||||
Se = sco_cursus.get_situation_etud_cursus(
|
Se = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
||||||
etud.to_dict_scodoc7(), formsemestre_id
|
if Se.prev_formsemestre:
|
||||||
)
|
ntp: NotesTableCompat = res_sem.load_formsemestre_results(
|
||||||
if Se.prev:
|
Se.prev_formsemestre
|
||||||
formsemestre_prev = FormSemestre.query.get_or_404(
|
|
||||||
Se.prev["formsemestre_id"]
|
|
||||||
)
|
)
|
||||||
ntp: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre_prev)
|
|
||||||
for ue in ntp.get_ues_stat_dict(filter_sport=True):
|
for ue in ntp.get_ues_stat_dict(filter_sport=True):
|
||||||
ue_status = ntp.get_etud_ue_status(etud.id, ue["ue_id"])
|
ue_status = ntp.get_etud_ue_status(etud.id, ue["ue_id"])
|
||||||
ue_code_s = (
|
ue_code_s = (
|
||||||
@ -110,7 +107,7 @@ def feuille_preparation_jury(formsemestre_id):
|
|||||||
moy_ue[ue_code_s][etud.id] = ue_status["moy"] if ue_status else ""
|
moy_ue[ue_code_s][etud.id] = ue_status["moy"] if ue_status else ""
|
||||||
ue_acro[ue_code_s] = (ue["numero"], ue["acronyme"], ue["titre"])
|
ue_acro[ue_code_s] = (ue["numero"], ue["acronyme"], ue["titre"])
|
||||||
|
|
||||||
if Se.prev:
|
if Se.prev_formsemestre:
|
||||||
try:
|
try:
|
||||||
moy_inter[etud.id] = (moy[etud.id] + prev_moy[etud.id]) / 2.0
|
moy_inter[etud.id] = (moy[etud.id] + prev_moy[etud.id]) / 2.0
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
|
@ -107,9 +107,7 @@ def dict_pvjury(
|
|||||||
D = {} # même chose que decisions, mais { etudid : dec }
|
D = {} # même chose que decisions, mais { etudid : dec }
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
etud = Identite.get_etud(etudid)
|
etud = Identite.get_etud(etudid)
|
||||||
situation_etud = sco_cursus.get_situation_etud_cursus(
|
situation_etud = sco_cursus.get_situation_etud_cursus(etud, formsemestre_id)
|
||||||
etud.to_dict_scodoc7(), formsemestre_id
|
|
||||||
)
|
|
||||||
semestre_non_terminal = (
|
semestre_non_terminal = (
|
||||||
semestre_non_terminal or situation_etud.semestre_non_terminal
|
semestre_non_terminal or situation_etud.semestre_non_terminal
|
||||||
)
|
)
|
||||||
@ -210,13 +208,13 @@ def dict_pvjury(
|
|||||||
if not info:
|
if not info:
|
||||||
continue # should not occur
|
continue # should not occur
|
||||||
etud = info[0]
|
etud = info[0]
|
||||||
if situation_etud.prev and situation_etud.prev_decision:
|
if situation_etud.prev_formsemestre and situation_etud.prev_decision:
|
||||||
d["prev_decision_sem"] = situation_etud.prev_decision
|
d["prev_decision_sem"] = situation_etud.prev_decision
|
||||||
d["prev_code"] = situation_etud.prev_decision["code"]
|
d["prev_code"] = situation_etud.prev_decision["code"]
|
||||||
d["prev_code_descr"] = _descr_decision_sem(
|
d["prev_code_descr"] = _descr_decision_sem(
|
||||||
scu.INSCRIT, situation_etud.prev_decision
|
scu.INSCRIT, situation_etud.prev_decision
|
||||||
)
|
)
|
||||||
d["prev"] = situation_etud.prev
|
d["prev"] = situation_etud.prev_formsemestre.to_dict()
|
||||||
has_prev = True
|
has_prev = True
|
||||||
else:
|
else:
|
||||||
d["prev_decision_sem"] = None
|
d["prev_decision_sem"] = None
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- mode: python -*-
|
# -*- mode: python -*-
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
SCOVERSION = "9.6.973"
|
SCOVERSION = "9.6.974"
|
||||||
|
|
||||||
SCONAME = "ScoDoc"
|
SCONAME = "ScoDoc"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user