forked from ScoDoc/ScoDoc
Exports Apogée: modernise code. Exporte RCUE du BUT: implements #925
This commit is contained in:
parent
320cfbebc8
commit
4ae484061e
@ -113,6 +113,12 @@ class ApcValidationRCUE(db.Model):
|
|||||||
"formsemestre_id": self.formsemestre_id,
|
"formsemestre_id": self.formsemestre_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_codes_apogee(self) -> set[str]:
|
||||||
|
"""Les codes Apogée associés à cette validation RCUE.
|
||||||
|
Prend les codes des deux UEs
|
||||||
|
"""
|
||||||
|
return self.ue1.get_codes_apogee_rcue() | self.ue2.get_codes_apogee_rcue()
|
||||||
|
|
||||||
|
|
||||||
class ApcValidationAnnee(db.Model):
|
class ApcValidationAnnee(db.Model):
|
||||||
"""Validation des années du BUT"""
|
"""Validation des années du BUT"""
|
||||||
|
@ -610,6 +610,41 @@ class FormSemestre(models.ScoDocModel):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def est_in_semestre_scolaire(
|
||||||
|
cls,
|
||||||
|
date_debut: datetime.date,
|
||||||
|
year=False,
|
||||||
|
periode=None,
|
||||||
|
mois_pivot_annee=scu.MONTH_DEBUT_ANNEE_SCOLAIRE,
|
||||||
|
mois_pivot_periode=scu.MONTH_DEBUT_PERIODE2,
|
||||||
|
) -> bool:
|
||||||
|
"""Vrai si la date_debut est dans la période indiquée (1,2,0)
|
||||||
|
du semestre `periode` de l'année scolaire indiquée
|
||||||
|
(ou, à défaut, de celle en cours).
|
||||||
|
|
||||||
|
La période utilise les même conventions que semset["sem_id"];
|
||||||
|
* 1 : première période
|
||||||
|
* 2 : deuxième période
|
||||||
|
* 0 ou période non précisée: annualisé (donc inclut toutes les périodes)
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
if not year:
|
||||||
|
year = scu.annee_scolaire()
|
||||||
|
# n'utilise pas le jour pivot
|
||||||
|
jour_pivot_annee = jour_pivot_periode = 1
|
||||||
|
# calcule l'année universitaire et la période
|
||||||
|
sem_annee, sem_periode = cls.comp_periode(
|
||||||
|
date_debut,
|
||||||
|
mois_pivot_annee,
|
||||||
|
mois_pivot_periode,
|
||||||
|
jour_pivot_annee,
|
||||||
|
jour_pivot_periode,
|
||||||
|
)
|
||||||
|
if periode is None or periode == 0:
|
||||||
|
return sem_annee == year
|
||||||
|
return sem_annee == year and sem_periode == periode
|
||||||
|
|
||||||
def est_terminal(self) -> bool:
|
def est_terminal(self) -> bool:
|
||||||
"Vrai si dernier semestre de son cursus (ou formation mono-semestre)"
|
"Vrai si dernier semestre de son cursus (ou formation mono-semestre)"
|
||||||
return (self.semestre_id < 0) or (
|
return (self.semestre_id < 0) or (
|
||||||
@ -1225,9 +1260,17 @@ class FormSemestreEtape(db.Model):
|
|||||||
"Etape False if code empty"
|
"Etape False if code empty"
|
||||||
return self.etape_apo is not None and (len(self.etape_apo) > 0)
|
return self.etape_apo is not None and (len(self.etape_apo) > 0)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, ApoEtapeVDI):
|
||||||
|
return self.as_apovdi() == other
|
||||||
|
return str(self) == str(other)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Etape {self.id} apo={self.etape_apo!r}>"
|
return f"<Etape {self.id} apo={self.etape_apo!r}>"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.etape_apo or ""
|
||||||
|
|
||||||
def as_apovdi(self) -> ApoEtapeVDI:
|
def as_apovdi(self) -> ApoEtapeVDI:
|
||||||
return ApoEtapeVDI(self.etape_apo)
|
return ApoEtapeVDI(self.etape_apo)
|
||||||
|
|
||||||
@ -1381,8 +1424,9 @@ class FormSemestreInscription(db.Model):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"""<{self.__class__.__name__} {self.id} etudid={self.etudid} sem={
|
return f"""<{self.__class__.__name__} {self.id} etudid={self.etudid} sem={
|
||||||
self.formsemestre_id} etat={self.etat} {
|
self.formsemestre_id} (S{self.formsemestre.semestre_id}) etat={self.etat} {
|
||||||
('parcours='+str(self.parcour)) if self.parcour else ''}>"""
|
('parcours="'+str(self.parcour.code)+'"') if self.parcour else ''
|
||||||
|
} {('etape="'+self.etape+'"') if self.etape else ''}>"""
|
||||||
|
|
||||||
|
|
||||||
class NotesSemSet(db.Model):
|
class NotesSemSet(db.Model):
|
||||||
|
@ -276,6 +276,12 @@ class UniteEns(models.ScoDocModel):
|
|||||||
return {x.strip() for x in self.code_apogee.split(",") if x}
|
return {x.strip() for x in self.code_apogee.split(",") if x}
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
|
def get_codes_apogee_rcue(self) -> set[str]:
|
||||||
|
"""Les codes Apogée RCUE (codés en base comme "VRT1,VRT2")"""
|
||||||
|
if self.code_apogee_rcue:
|
||||||
|
return {x.strip() for x in self.code_apogee_rcue.split(",") if x}
|
||||||
|
return set()
|
||||||
|
|
||||||
def _parcours_niveaux_ids(self, parcours=list[ApcParcours]) -> set[int]:
|
def _parcours_niveaux_ids(self, parcours=list[ApcParcours]) -> set[int]:
|
||||||
"""set des ids de niveaux communs à tous les parcours listés"""
|
"""set des ids de niveaux communs à tous les parcours listés"""
|
||||||
return set.intersection(
|
return set.intersection(
|
||||||
|
@ -43,12 +43,11 @@ import re
|
|||||||
import time
|
import time
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from flask import send_file
|
from flask import g, send_file
|
||||||
import numpy as np
|
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.models import (
|
from app.models import (
|
||||||
@ -79,7 +78,6 @@ from app.scodoc.codes_cursus import (
|
|||||||
)
|
)
|
||||||
from app.scodoc import sco_cursus
|
from app.scodoc import sco_cursus
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_etud
|
|
||||||
|
|
||||||
|
|
||||||
def _apo_fmt_note(note, fmt="%3.2f"):
|
def _apo_fmt_note(note, fmt="%3.2f"):
|
||||||
@ -99,7 +97,7 @@ class EtuCol:
|
|||||||
"""Valeurs colonnes d'un element pour un etudiant"""
|
"""Valeurs colonnes d'un element pour un etudiant"""
|
||||||
|
|
||||||
def __init__(self, nip, apo_elt, init_vals):
|
def __init__(self, nip, apo_elt, init_vals):
|
||||||
pass # XXX
|
pass
|
||||||
|
|
||||||
|
|
||||||
ETUD_OK = "ok"
|
ETUD_OK = "ok"
|
||||||
@ -150,9 +148,9 @@ class ApoEtud(dict):
|
|||||||
_apo_fmt_note, fmt=ScoDocSiteConfig.get_code_apo("NOTES_FMT") or "3.2f"
|
_apo_fmt_note, fmt=ScoDocSiteConfig.get_code_apo("NOTES_FMT") or "3.2f"
|
||||||
)
|
)
|
||||||
# Initialisés par associate_sco:
|
# Initialisés par associate_sco:
|
||||||
self.autre_sem: dict = None
|
self.autre_formsemestre: FormSemestre = None
|
||||||
self.autre_res: NotesTableCompat = None
|
self.autre_res: NotesTableCompat = None
|
||||||
self.cur_sem: dict = None
|
self.cur_formsemestre: FormSemestre = None
|
||||||
self.cur_res: NotesTableCompat = None
|
self.cur_res: NotesTableCompat = None
|
||||||
self.new_cols = {}
|
self.new_cols = {}
|
||||||
"{ col_id : value to record in csv }"
|
"{ col_id : value to record in csv }"
|
||||||
@ -222,7 +220,8 @@ class ApoEtud(dict):
|
|||||||
self.new_cols[col_id] = self.cols[col_id]
|
self.new_cols[col_id] = self.cols[col_id]
|
||||||
except KeyError as exc:
|
except KeyError as exc:
|
||||||
raise ScoFormatError(
|
raise ScoFormatError(
|
||||||
f"""Fichier Apogee invalide : ligne mal formatée ? <br>colonne <tt>{col_id}</tt> non déclarée ?"""
|
f"""Fichier Apogee invalide : ligne mal formatée ? <br>colonne <tt>{
|
||||||
|
col_id}</tt> non déclarée ?"""
|
||||||
) from exc
|
) from exc
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
@ -248,7 +247,7 @@ class ApoEtud(dict):
|
|||||||
# codes = set([apo_data.apo_csv.cols[col_id].code for col_id in apo_data.apo_csv.col_ids])
|
# codes = set([apo_data.apo_csv.cols[col_id].code for col_id in apo_data.apo_csv.col_ids])
|
||||||
# return codes - set(sco_elts)
|
# return codes - set(sco_elts)
|
||||||
|
|
||||||
def search_elt_in_sem(self, code, sem) -> dict:
|
def search_elt_in_sem(self, code: str, sem: dict) -> dict:
|
||||||
"""
|
"""
|
||||||
VET code jury etape (en BUT, le code annuel)
|
VET code jury etape (en BUT, le code annuel)
|
||||||
ELP élément pédagogique: UE, module
|
ELP élément pédagogique: UE, module
|
||||||
@ -263,8 +262,8 @@ class ApoEtud(dict):
|
|||||||
sem (dict): semestre dans lequel on cherche l'élément
|
sem (dict): semestre dans lequel on cherche l'élément
|
||||||
|
|
||||||
Utilise notamment:
|
Utilise notamment:
|
||||||
cur_sem (dict): semestre "courant" pour résultats annuels (VET)
|
cur_formsemestre : semestre "courant" pour résultats annuels (VET)
|
||||||
autre_sem (dict): autre semestre utilisé pour calculer les résultats annuels (VET)
|
autre_formsemestre : autre formsemestre utilisé pour 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é
|
||||||
@ -314,10 +313,10 @@ class ApoEtud(dict):
|
|||||||
code in {x.strip() for x in sem["elt_annee_apo"].split(",")}
|
code in {x.strip() for x in sem["elt_annee_apo"].split(",")}
|
||||||
):
|
):
|
||||||
export_res_etape = self.export_res_etape
|
export_res_etape = self.export_res_etape
|
||||||
if (not export_res_etape) and self.cur_sem:
|
if (not export_res_etape) and self.cur_formsemestre:
|
||||||
# exporte toujours le résultat de l'étape si l'étudiant est diplômé
|
# exporte toujours le résultat de l'étape si l'étudiant est diplômé
|
||||||
Se = sco_cursus.get_situation_etud_cursus(
|
Se = sco_cursus.get_situation_etud_cursus(
|
||||||
self.etud, self.cur_sem["formsemestre_id"]
|
self.etud, self.cur_formsemestre.id
|
||||||
)
|
)
|
||||||
export_res_etape = Se.all_other_validated()
|
export_res_etape = Se.all_other_validated()
|
||||||
|
|
||||||
@ -375,8 +374,20 @@ class ApoEtud(dict):
|
|||||||
|
|
||||||
if module_code_found:
|
if module_code_found:
|
||||||
return VOID_APO_RES
|
return VOID_APO_RES
|
||||||
|
|
||||||
# RCUE du BUT
|
# RCUE du BUT
|
||||||
deca = jury_but.DecisionsProposeesAnnee(self.etud, formsemestre)
|
if res.is_apc:
|
||||||
|
for val_rcue in ApcValidationRCUE.query.filter_by(
|
||||||
|
etudid=etudid, formsemestre_id=sem["formsemestre_id"]
|
||||||
|
):
|
||||||
|
if code in val_rcue.get_codes_apogee():
|
||||||
|
return dict(
|
||||||
|
N="", # n'exporte pas de moyenne RCUE
|
||||||
|
B=20,
|
||||||
|
J="",
|
||||||
|
R=ScoDocSiteConfig.get_code_apo(val_rcue.code),
|
||||||
|
M="",
|
||||||
|
)
|
||||||
#
|
#
|
||||||
return None # element Apogee non trouvé dans ce semestre
|
return None # element Apogee non trouvé dans ce semestre
|
||||||
|
|
||||||
@ -418,11 +429,10 @@ class ApoEtud(dict):
|
|||||||
#
|
#
|
||||||
# XXX cette règle est discutable, à valider
|
# XXX cette règle est discutable, à valider
|
||||||
|
|
||||||
# log('comp_elt_annuel cur_sem=%s autre_sem=%s' % (cur_sem['formsemestre_id'], autre_sem['formsemestre_id']))
|
if not self.cur_formsemestre:
|
||||||
if not self.cur_sem:
|
|
||||||
# l'étudiant n'a pas de semestre courant ?!
|
# l'étudiant n'a pas de semestre courant ?!
|
||||||
self.log.append("pas de semestre courant")
|
self.log.append("pas de semestre courant")
|
||||||
log(f"comp_elt_annuel: etudid {etudid} has no cur_sem")
|
log(f"comp_elt_annuel: etudid {etudid} has no cur_formsemestre")
|
||||||
return VOID_APO_RES
|
return VOID_APO_RES
|
||||||
|
|
||||||
if self.is_apc:
|
if self.is_apc:
|
||||||
@ -438,7 +448,7 @@ class ApoEtud(dict):
|
|||||||
# ne touche pas aux RATs
|
# ne touche pas aux RATs
|
||||||
return VOID_APO_RES
|
return VOID_APO_RES
|
||||||
|
|
||||||
if not self.autre_sem:
|
if not self.autre_formsemestre:
|
||||||
# formations monosemestre, ou code VET semestriel,
|
# formations monosemestre, ou code VET semestriel,
|
||||||
# ou jury intermediaire et etudiant non redoublant...
|
# ou jury intermediaire et etudiant non redoublant...
|
||||||
return self.comp_elt_semestre(self.cur_res, cur_decision, etudid)
|
return self.comp_elt_semestre(self.cur_res, cur_decision, etudid)
|
||||||
@ -518,7 +528,7 @@ class ApoEtud(dict):
|
|||||||
self.validation_annee_but: ApcValidationAnnee = (
|
self.validation_annee_but: ApcValidationAnnee = (
|
||||||
ApcValidationAnnee.query.filter_by(
|
ApcValidationAnnee.query.filter_by(
|
||||||
formsemestre_id=formsemestre.id,
|
formsemestre_id=formsemestre.id,
|
||||||
etudid=self.etud["etudid"],
|
etudid=self.etud.id,
|
||||||
referentiel_competence_id=self.cur_res.formsemestre.formation.referentiel_competence_id,
|
referentiel_competence_id=self.cur_res.formsemestre.formation.referentiel_competence_id,
|
||||||
).first()
|
).first()
|
||||||
)
|
)
|
||||||
@ -527,7 +537,7 @@ class ApoEtud(dict):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def etud_set_semestres_de_etape(self, apo_data: "ApoData"):
|
def etud_set_semestres_de_etape(self, apo_data: "ApoData"):
|
||||||
"""Set .cur_sem and .autre_sem et charge les résultats.
|
"""Set .cur_formsemestre and .autre_formsemestre et charge les résultats.
|
||||||
Lorsqu'on a une formation semestrialisée mais avec un code étape annuel,
|
Lorsqu'on a une formation semestrialisée mais avec un code étape annuel,
|
||||||
il faut considérer les deux semestres ((S1,S2) ou (S3,S4)) pour calculer
|
il faut considérer les deux semestres ((S1,S2) ou (S3,S4)) pour calculer
|
||||||
le code annuel (VET ou VRT1A (voir elt_annee_apo)).
|
le code annuel (VET ou VRT1A (voir elt_annee_apo)).
|
||||||
@ -535,52 +545,49 @@ class ApoEtud(dict):
|
|||||||
Pour les jurys intermediaires (janvier, S1 ou S3): (S2 ou S4) de la même
|
Pour les jurys intermediaires (janvier, S1 ou S3): (S2 ou S4) de la même
|
||||||
étape lors d'une année précédente ?
|
étape lors d'une année précédente ?
|
||||||
|
|
||||||
Set cur_sem: le semestre "courant" et autre_sem, ou None s'il n'y en a pas.
|
Set cur_formsemestre: le formsemestre "courant"
|
||||||
|
et autre_formsemestre, ou None s'il n'y en a pas.
|
||||||
"""
|
"""
|
||||||
# Cherche le semestre "courant":
|
# Cherche le formsemestre "courant":
|
||||||
cur_sems = [
|
cur_formsemestres = [
|
||||||
sem
|
formsemestre
|
||||||
for sem in self.etud["sems"]
|
for formsemestre in self.etud.get_formsemestres()
|
||||||
if (
|
if (
|
||||||
(sem["semestre_id"] == apo_data.cur_semestre_id)
|
(formsemestre.semestre_id == apo_data.cur_semestre_id)
|
||||||
and (apo_data.etape in sem["etapes"])
|
and (apo_data.etape in formsemestre.etapes)
|
||||||
and (
|
and (
|
||||||
sco_formsemestre.sem_in_semestre_scolaire(
|
FormSemestre.est_in_semestre_scolaire(
|
||||||
sem,
|
formsemestre.date_debut,
|
||||||
apo_data.annee_scolaire,
|
apo_data.annee_scolaire,
|
||||||
0, # annee complete
|
0, # annee complete
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
if not cur_sems:
|
cur_formsemestre = None
|
||||||
cur_sem = None
|
if cur_formsemestres:
|
||||||
else:
|
# prend le plus récent avec décision
|
||||||
# prend le plus recent avec decision
|
for formsemestre in cur_formsemestres:
|
||||||
cur_sem = None
|
|
||||||
for sem in cur_sems:
|
|
||||||
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
|
||||||
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
has_decision = res.etud_has_decision(self.etud["etudid"])
|
has_decision = res.etud_has_decision(self.etud.id)
|
||||||
if has_decision:
|
if has_decision:
|
||||||
cur_sem = sem
|
cur_formsemestre = formsemestre
|
||||||
self.cur_res = res
|
self.cur_res = res
|
||||||
break
|
break
|
||||||
if cur_sem is None:
|
if cur_formsemestres is None:
|
||||||
cur_sem = cur_sems[0] # aucun avec décision, prend le plus recent
|
cur_formsemestre = cur_formsemestres[
|
||||||
if res.formsemestre.id == cur_sem["formsemestre_id"]:
|
0
|
||||||
|
] # aucun avec décision, prend le plus recent
|
||||||
|
if res.formsemestre.id == cur_formsemestre.id:
|
||||||
self.cur_res = res
|
self.cur_res = res
|
||||||
else:
|
else:
|
||||||
formsemestre = FormSemestre.query.get_or_404(
|
self.cur_res = res_sem.load_formsemestre_results(cur_formsemestre)
|
||||||
cur_sem["formsemestre_id"]
|
|
||||||
)
|
|
||||||
self.cur_res = res_sem.load_formsemestre_results(formsemestre)
|
|
||||||
|
|
||||||
self.cur_sem = cur_sem
|
self.cur_formsemestre = cur_formsemestre
|
||||||
|
|
||||||
if apo_data.cur_semestre_id <= 0:
|
if apo_data.cur_semestre_id <= 0:
|
||||||
# "autre_sem" non pertinent pour sessions sans semestres:
|
# autre_formsemestre non pertinent pour sessions sans semestres:
|
||||||
self.autre_sem = None
|
self.autre_formsemestre = None
|
||||||
self.autre_res = None
|
self.autre_res = None
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -601,52 +608,49 @@ class ApoEtud(dict):
|
|||||||
courant_mois_debut = 1 # ou 2 (fev-jul)
|
courant_mois_debut = 1 # ou 2 (fev-jul)
|
||||||
else:
|
else:
|
||||||
raise ValueError("invalid periode value !") # bug ?
|
raise ValueError("invalid periode value !") # bug ?
|
||||||
courant_date_debut = "%d-%02d-01" % (
|
courant_date_debut = datetime.date(
|
||||||
courant_annee_debut,
|
day=1, month=courant_mois_debut, year=courant_annee_debut
|
||||||
courant_mois_debut,
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
courant_date_debut = "9999-99-99"
|
courant_date_debut = datetime.date(day=31, month=12, year=9999)
|
||||||
|
|
||||||
# etud['sems'] est la liste des semestres de l'étudiant, triés par date,
|
|
||||||
# le plus récemment effectué en tête.
|
|
||||||
# Cherche les semestres (antérieurs) de l'indice autre de la même étape apogée
|
# Cherche les semestres (antérieurs) de l'indice autre de la même étape apogée
|
||||||
# s'il y en a plusieurs, choisit le plus récent ayant une décision
|
# s'il y en a plusieurs, choisit le plus récent ayant une décision
|
||||||
|
|
||||||
autres_sems = []
|
autres_sems = []
|
||||||
for sem in self.etud["sems"]:
|
for formsemestre in self.etud.get_formsemestres():
|
||||||
if (
|
if (
|
||||||
sem["semestre_id"] == autre_semestre_id
|
formsemestre.semestre_id == autre_semestre_id
|
||||||
and apo_data.etape_apogee in sem["etapes"]
|
and apo_data.etape_apogee in formsemestre.etapes
|
||||||
):
|
):
|
||||||
if (
|
if (
|
||||||
sem["date_debut_iso"] < courant_date_debut
|
formsemestre.date_debut < courant_date_debut
|
||||||
): # on demande juste qu'il ait démarré avant
|
): # on demande juste qu'il ait démarré avant
|
||||||
autres_sems.append(sem)
|
autres_sems.append(formsemestre)
|
||||||
if not autres_sems:
|
if not autres_sems:
|
||||||
autre_sem = None
|
autre_formsemestre = None
|
||||||
elif len(autres_sems) == 1:
|
elif len(autres_sems) == 1:
|
||||||
autre_sem = autres_sems[0]
|
autre_formsemestre = autres_sems[0]
|
||||||
else:
|
else:
|
||||||
autre_sem = None
|
autre_formsemestre = None
|
||||||
for sem in autres_sems:
|
for formsemestre in autres_sems:
|
||||||
formsemestre = FormSemestre.query.get_or_404(sem["formsemestre_id"])
|
|
||||||
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
res: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||||
if res.is_apc:
|
if res.is_apc:
|
||||||
has_decision = res.etud_has_decision(self.etud["etudid"])
|
has_decision = res.etud_has_decision(self.etud.id)
|
||||||
else:
|
else:
|
||||||
has_decision = res.get_etud_decision_sem(self.etud["etudid"])
|
has_decision = res.get_etud_decision_sem(self.etud.id)
|
||||||
if has_decision:
|
if has_decision:
|
||||||
autre_sem = sem
|
autre_formsemestre = formsemestre
|
||||||
break
|
break
|
||||||
if autre_sem is None:
|
if autre_formsemestre is None:
|
||||||
autre_sem = autres_sems[0] # aucun avec decision, prend le plus recent
|
autre_formsemestre = autres_sems[
|
||||||
|
0
|
||||||
|
] # aucun avec decision, prend le plus recent
|
||||||
|
|
||||||
self.autre_sem = autre_sem
|
self.autre_formsemestre = autre_formsemestre
|
||||||
# Charge les résultats:
|
# Charge les résultats:
|
||||||
if autre_sem:
|
if autre_formsemestre:
|
||||||
formsemestre = FormSemestre.query.get_or_404(autre_sem["formsemestre_id"])
|
self.autre_res = res_sem.load_formsemestre_results(self.autre_formsemestre)
|
||||||
self.autre_res = res_sem.load_formsemestre_results(formsemestre)
|
|
||||||
else:
|
else:
|
||||||
self.autre_res = None
|
self.autre_res = None
|
||||||
|
|
||||||
@ -873,6 +877,16 @@ class ApoData:
|
|||||||
codes_ues = set().union(
|
codes_ues = set().union(
|
||||||
*[ue.get_codes_apogee() for ue in formsemestre.get_ues(with_sport=True)]
|
*[ue.get_codes_apogee() for ue in formsemestre.get_ues(with_sport=True)]
|
||||||
)
|
)
|
||||||
|
codes_rcues = (
|
||||||
|
set().union(
|
||||||
|
*[
|
||||||
|
ue.get_codes_apogee_rcue()
|
||||||
|
for ue in formsemestre.get_ues(with_sport=True)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if self.is_apc
|
||||||
|
else set()
|
||||||
|
)
|
||||||
s = set()
|
s = set()
|
||||||
codes_by_sem[sem["formsemestre_id"]] = s
|
codes_by_sem[sem["formsemestre_id"]] = s
|
||||||
for col_id in self.apo_csv.col_ids[4:]:
|
for col_id in self.apo_csv.col_ids[4:]:
|
||||||
@ -885,9 +899,14 @@ class ApoData:
|
|||||||
if code in codes_ues:
|
if code in codes_ues:
|
||||||
s.add(code)
|
s.add(code)
|
||||||
continue
|
continue
|
||||||
|
# associé à un RCUE BUT
|
||||||
|
if code in codes_rcues:
|
||||||
|
s.add(code)
|
||||||
|
continue
|
||||||
# associé à un module:
|
# associé à un module:
|
||||||
if code in codes_modules:
|
if code in codes_modules:
|
||||||
s.add(code)
|
s.add(code)
|
||||||
|
|
||||||
# log('codes_by_sem=%s' % pprint.pformat(codes_by_sem))
|
# log('codes_by_sem=%s' % pprint.pformat(codes_by_sem))
|
||||||
return codes_by_sem
|
return codes_by_sem
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ class BaseArchiver:
|
|||||||
dirs = glob.glob(base + "*")
|
dirs = glob.glob(base + "*")
|
||||||
return [os.path.split(x)[1] for x in dirs]
|
return [os.path.split(x)[1] for x in dirs]
|
||||||
|
|
||||||
def list_obj_archives(self, oid: int, dept_id: int = None):
|
def list_obj_archives(self, oid: int, dept_id: int = None) -> list[str]:
|
||||||
"""Returns
|
"""Returns
|
||||||
:return: list of archive identifiers for this object (paths to non empty dirs)
|
:return: list of archive identifiers for this object (paths to non empty dirs)
|
||||||
"""
|
"""
|
||||||
|
@ -291,14 +291,14 @@ class SituationEtudCursusClassic(SituationEtudCursus):
|
|||||||
if s_idx == NO_SEMESTRE_ID or s_idx > 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, s_idx))):
|
if self._sem_list_validated(set(range(1, s_idx))):
|
||||||
# antérieurs validé, teste suivant
|
# antérieurs validés, teste suivant
|
||||||
n1 = s_idx + 1
|
n1 = s_idx + 1
|
||||||
for sem in self.get_semestres():
|
for formsemestre in self.formsemestres:
|
||||||
if (
|
if (
|
||||||
sem["semestre_id"] == n1
|
formsemestre.semestre_id == n1
|
||||||
and sem["formation_code"] == self.formation.formation_code
|
and formsemestre.formation.formation_code
|
||||||
|
== self.formation.formation_code
|
||||||
):
|
):
|
||||||
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
|
||||||
)
|
)
|
||||||
|
@ -84,6 +84,7 @@ _ueEditor = ndb.EditableTable(
|
|||||||
"ects",
|
"ects",
|
||||||
"is_external",
|
"is_external",
|
||||||
"code_apogee",
|
"code_apogee",
|
||||||
|
"code_apogee_rcue",
|
||||||
"coefficient",
|
"coefficient",
|
||||||
"coef_rcue",
|
"coef_rcue",
|
||||||
"color",
|
"color",
|
||||||
@ -425,6 +426,20 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
|
|||||||
"max_length": APO_CODE_STR_LEN,
|
"max_length": APO_CODE_STR_LEN,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
]
|
||||||
|
if is_apc:
|
||||||
|
form_descr += [
|
||||||
|
(
|
||||||
|
"code_apogee_rcue",
|
||||||
|
{
|
||||||
|
"title": "Code Apogée du RCUE",
|
||||||
|
"size": 25,
|
||||||
|
"explanation": "(optionnel) code(s) élément pédagogique Apogée du RCUE",
|
||||||
|
"max_length": APO_CODE_STR_LEN,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
form_descr += [
|
||||||
(
|
(
|
||||||
"is_external",
|
"is_external",
|
||||||
{
|
{
|
||||||
|
@ -247,9 +247,7 @@ def apo_csv_check_etape(semset, set_nips, etape_apo):
|
|||||||
return nips_ok, apo_nips, nips_no_apo, nips_no_sco, maq_elems, sem_elems
|
return nips_ok, apo_nips, nips_no_apo, nips_no_sco, maq_elems, sem_elems
|
||||||
|
|
||||||
|
|
||||||
def apo_csv_semset_check(
|
def apo_csv_semset_check(semset, allow_missing_apo=False, allow_missing_csv=False):
|
||||||
semset, allow_missing_apo=False, allow_missing_csv=False
|
|
||||||
): # was apo_csv_check
|
|
||||||
"""
|
"""
|
||||||
check students in stored maqs vs students in semset
|
check students in stored maqs vs students in semset
|
||||||
Cas à détecter:
|
Cas à détecter:
|
||||||
@ -346,120 +344,3 @@ def apo_csv_retreive_etuds_by_nip(semset, nips):
|
|||||||
etuds[nip] = apo_etuds_by_nips.get(nip, {"nip": nip, "etape_apo": "?"})
|
etuds[nip] = apo_etuds_by_nips.get(nip, {"nip": nip, "etape_apo": "?"})
|
||||||
|
|
||||||
return etuds
|
return etuds
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
Tests:
|
|
||||||
|
|
||||||
from debug import *
|
|
||||||
from app.scodoc import sco_groups
|
|
||||||
from app.scodoc import sco_groups_view
|
|
||||||
from app.scodoc import sco_formsemestre
|
|
||||||
from app.scodoc.sco_etape_apogee import *
|
|
||||||
from app.scodoc.sco_apogee_csv import *
|
|
||||||
from app.scodoc.sco_semset import *
|
|
||||||
|
|
||||||
app.set_sco_dept('RT')
|
|
||||||
csv_data = open('/opt/misc/VDTRT_V1RT.TXT').read()
|
|
||||||
annee_scolaire=2015
|
|
||||||
sem_id=1
|
|
||||||
|
|
||||||
apo_data = sco_apogee_csv.ApoData(csv_data, periode=sem_id)
|
|
||||||
print apo_data.etape_apogee
|
|
||||||
|
|
||||||
apo_data.setup()
|
|
||||||
e = apo_data.etuds[0]
|
|
||||||
e.lookup_scodoc( apo_data.etape_formsemestre_ids)
|
|
||||||
e.associate_sco( apo_data)
|
|
||||||
|
|
||||||
print apo_csv_list_stored_archives()
|
|
||||||
|
|
||||||
|
|
||||||
# apo_csv_store(csv_data, annee_scolaire, sem_id)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
groups_infos = sco_groups_view.DisplayedGroupsInfos( [sco_groups.get_default_group(formsemestre_id)], formsemestre_id=formsemestre_id)
|
|
||||||
|
|
||||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
|
||||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
|
||||||
#
|
|
||||||
s = SemSet('NSS29902')
|
|
||||||
apo_data = sco_apogee_csv.ApoData(open('/opt/scodoc/var/scodoc/archives/apo_csv/RT/2015-2/2016-07-10-11-26-15/V1RT.csv').read(), periode=1)
|
|
||||||
|
|
||||||
# cas Tiziri K. (inscrite en S1, démission en fin de S1, pas inscrite en S2)
|
|
||||||
# => pas de décision, ce qui est voulu (?)
|
|
||||||
#
|
|
||||||
|
|
||||||
apo_data.setup()
|
|
||||||
e = [ e for e in apo_data.etuds if e['nom'] == 'XYZ' ][0]
|
|
||||||
e.lookup_scodoc( apo_data.etape_formsemestre_ids)
|
|
||||||
e.associate_sco(apo_data)
|
|
||||||
|
|
||||||
self=e
|
|
||||||
col_id='apoL_c0129'
|
|
||||||
|
|
||||||
# --
|
|
||||||
from app.scodoc import sco_portal_apogee
|
|
||||||
_ = go_dept(app, 'GEA').Notes
|
|
||||||
#csv_data = sco_portal_apogee.get_maquette_apogee(etape='V1GE', annee_scolaire=2015)
|
|
||||||
csv_data = open('/tmp/V1GE.txt').read()
|
|
||||||
apo_data = sco_apogee_csv.ApoData(csv_data, periode=1)
|
|
||||||
|
|
||||||
|
|
||||||
# ------
|
|
||||||
# les elements inconnus:
|
|
||||||
|
|
||||||
from debug import *
|
|
||||||
from app.scodoc import sco_groups
|
|
||||||
from app.scodoc import sco_groups_view
|
|
||||||
from app.scodoc import sco_formsemestre
|
|
||||||
from app.scodoc.sco_etape_apogee import *
|
|
||||||
from app.scodoc.sco_apogee_csv import *
|
|
||||||
from app.scodoc.sco_semset import *
|
|
||||||
|
|
||||||
_ = go_dept(app, 'RT').Notes
|
|
||||||
csv_data = open('/opt/misc/V2RT.csv').read()
|
|
||||||
annee_scolaire=2015
|
|
||||||
sem_id=1
|
|
||||||
|
|
||||||
apo_data = sco_apogee_csv.ApoData(csv_data, periode=1)
|
|
||||||
print apo_data.etape_apogee
|
|
||||||
|
|
||||||
apo_data.setup()
|
|
||||||
for e in apo_data.etuds:
|
|
||||||
e.lookup_scodoc( apo_data.etape_formsemestre_ids)
|
|
||||||
e.associate_sco(apo_data)
|
|
||||||
|
|
||||||
# ------
|
|
||||||
# test export jury intermediaire
|
|
||||||
from debug import *
|
|
||||||
from app.scodoc import sco_groups
|
|
||||||
from app.scodoc import sco_groups_view
|
|
||||||
from app.scodoc import sco_formsemestre
|
|
||||||
from app.scodoc.sco_etape_apogee import *
|
|
||||||
from app.scodoc.sco_apogee_csv import *
|
|
||||||
from app.scodoc.sco_semset import *
|
|
||||||
|
|
||||||
_ = go_dept(app, 'CJ').Notes
|
|
||||||
csv_data = open('/opt/scodoc/var/scodoc/archives/apo_csv/CJ/2016-1/2017-03-06-21-46-32/V1CJ.csv').read()
|
|
||||||
annee_scolaire=2016
|
|
||||||
sem_id=1
|
|
||||||
|
|
||||||
apo_data = sco_apogee_csv.ApoData(csv_data, periode=1)
|
|
||||||
print apo_data.etape_apogee
|
|
||||||
|
|
||||||
apo_data.setup()
|
|
||||||
e = [ e for e in apo_data.etuds if e['nom'] == 'XYZ' ][0] #
|
|
||||||
e.lookup_scodoc( apo_data.etape_formsemestre_ids)
|
|
||||||
e.associate_sco(apo_data)
|
|
||||||
|
|
||||||
self=e
|
|
||||||
|
|
||||||
sco_elts = {}
|
|
||||||
col_id='apoL_c0001'
|
|
||||||
code = apo_data.cols[col_id]['Code'] # 'V1RT'
|
|
||||||
|
|
||||||
sem = apo_data.sems_periode[0] # le S1
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
@ -125,14 +125,19 @@ def apo_semset_maq_status(
|
|||||||
H.append("""<p><em>Aucune maquette chargée</em></p>""")
|
H.append("""<p><em>Aucune maquette chargée</em></p>""")
|
||||||
# Upload fichier:
|
# Upload fichier:
|
||||||
H.append(
|
H.append(
|
||||||
"""<form id="apo_csv_add" action="view_apo_csv_store" method="post" enctype="multipart/form-data">
|
f"""<form id="apo_csv_add" action="view_apo_csv_store"
|
||||||
Charger votre fichier maquette Apogée:
|
method="post" enctype="multipart/form-data"
|
||||||
|
style="margin-bottom: 8px;"
|
||||||
|
>
|
||||||
|
<div style="margin-top: 12px; margin-bottom: 8px;">
|
||||||
|
{'Charger votre fichier' if tab_archives.is_empty() else 'Ajouter un autre fichier'}
|
||||||
|
maquette Apogée:
|
||||||
|
</div>
|
||||||
<input type="file" size="30" name="csvfile"/>
|
<input type="file" size="30" name="csvfile"/>
|
||||||
<input type="hidden" name="semset_id" value="%s"/>
|
<input type="hidden" name="semset_id" value="{semset_id}"/>
|
||||||
<input type="submit" value="Ajouter ce fichier"/>
|
<input type="submit" value="Ajouter ce fichier"/>
|
||||||
<input type="checkbox" name="autodetect" checked/>autodétecter encodage</input>
|
<input type="checkbox" name="autodetect" checked/>autodétecter encodage</input>
|
||||||
</form>"""
|
</form>"""
|
||||||
% (semset_id,)
|
|
||||||
)
|
)
|
||||||
# Récupération sur portail:
|
# Récupération sur portail:
|
||||||
maquette_url = sco_portal_apogee.get_maquette_url()
|
maquette_url = sco_portal_apogee.get_maquette_url()
|
||||||
@ -335,7 +340,7 @@ def apo_semset_maq_status(
|
|||||||
missing = maq_elems - sem_elems
|
missing = maq_elems - sem_elems
|
||||||
H.append('<div id="apo_elements">')
|
H.append('<div id="apo_elements">')
|
||||||
H.append(
|
H.append(
|
||||||
'<p>Elements Apogée: <span class="apo_elems">%s</span></p>'
|
'<p>Élements Apogée: <span class="apo_elems">%s</span></p>'
|
||||||
% ", ".join(
|
% ", ".join(
|
||||||
[
|
[
|
||||||
e if not e in missing else '<span class="missing">' + e + "</span>"
|
e if not e in missing else '<span class="missing">' + e + "</span>"
|
||||||
@ -351,7 +356,7 @@ def apo_semset_maq_status(
|
|||||||
]
|
]
|
||||||
H.append(
|
H.append(
|
||||||
f"""<div class="apo_csv_status_missing_elems">
|
f"""<div class="apo_csv_status_missing_elems">
|
||||||
<span class="fontred">Elements Apogée absents dans ScoDoc: </span>
|
<span class="fontred">Élements Apogée absents dans ScoDoc: </span>
|
||||||
<span class="apo_elems fontred">{
|
<span class="apo_elems fontred">{
|
||||||
", ".join(sorted(missing))
|
", ".join(sorted(missing))
|
||||||
}</span>
|
}</span>
|
||||||
@ -442,11 +447,11 @@ def table_apo_csv_list(semset):
|
|||||||
annee_scolaire = semset["annee_scolaire"]
|
annee_scolaire = semset["annee_scolaire"]
|
||||||
sem_id = semset["sem_id"]
|
sem_id = semset["sem_id"]
|
||||||
|
|
||||||
T = sco_etape_apogee.apo_csv_list_stored_archives(
|
rows = sco_etape_apogee.apo_csv_list_stored_archives(
|
||||||
annee_scolaire, sem_id, etapes=semset.list_etapes()
|
annee_scolaire, sem_id, etapes=semset.list_etapes()
|
||||||
)
|
)
|
||||||
|
|
||||||
for t in T:
|
for t in rows:
|
||||||
# Ajoute qq infos pour affichage:
|
# Ajoute qq infos pour affichage:
|
||||||
csv_data = sco_etape_apogee.apo_csv_get(t["etape_apo"], annee_scolaire, sem_id)
|
csv_data = sco_etape_apogee.apo_csv_get(t["etape_apo"], annee_scolaire, sem_id)
|
||||||
apo_data = sco_apogee_csv.ApoData(csv_data, periode=semset["sem_id"])
|
apo_data = sco_apogee_csv.ApoData(csv_data, periode=semset["sem_id"])
|
||||||
@ -484,7 +489,7 @@ def table_apo_csv_list(semset):
|
|||||||
"date_str": "Enregistré le",
|
"date_str": "Enregistré le",
|
||||||
},
|
},
|
||||||
columns_ids=columns_ids,
|
columns_ids=columns_ids,
|
||||||
rows=T,
|
rows=rows,
|
||||||
html_class="table_leftalign apo_maq_list",
|
html_class="table_leftalign apo_maq_list",
|
||||||
html_sortable=True,
|
html_sortable=True,
|
||||||
# base_url = '%s?formsemestre_id=%s' % (request.base_url, formsemestre_id),
|
# base_url = '%s?formsemestre_id=%s' % (request.base_url, formsemestre_id),
|
||||||
|
@ -93,7 +93,7 @@ import json
|
|||||||
|
|
||||||
from flask import url_for, g
|
from flask import url_for, g
|
||||||
|
|
||||||
from app.scodoc.sco_portal_apogee import get_inscrits_etape
|
from app.scodoc import sco_portal_apogee
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc.sco_utils import annee_scolaire_debut
|
from app.scodoc.sco_utils import annee_scolaire_debut
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
@ -136,11 +136,16 @@ class DataEtudiant(object):
|
|||||||
self.etudid = etudid
|
self.etudid = etudid
|
||||||
self.data_apogee = None
|
self.data_apogee = None
|
||||||
self.data_scodoc = None
|
self.data_scodoc = None
|
||||||
self.etapes = set() # l'ensemble des étapes où il est inscrit
|
self.etapes = set()
|
||||||
self.semestres = set() # l'ensemble des formsemestre_id où il est inscrit
|
"l'ensemble des étapes où il est inscrit"
|
||||||
self.tags = set() # les anomalies relevées
|
self.semestres = set()
|
||||||
self.ind_row = "-" # là où il compte dans les effectifs (ligne et colonne)
|
"l'ensemble des formsemestre_id où il est inscrit"
|
||||||
|
self.tags = set()
|
||||||
|
"les anomalies relevées"
|
||||||
|
self.ind_row = "-"
|
||||||
|
"ligne où il compte dans les effectifs"
|
||||||
self.ind_col = "-"
|
self.ind_col = "-"
|
||||||
|
"colonne où il compte dans les effectifs"
|
||||||
|
|
||||||
def add_etape(self, etape):
|
def add_etape(self, etape):
|
||||||
self.etapes.add(etape)
|
self.etapes.add(etape)
|
||||||
@ -163,9 +168,9 @@ class DataEtudiant(object):
|
|||||||
def set_ind_col(self, indicatif):
|
def set_ind_col(self, indicatif):
|
||||||
self.ind_col = indicatif
|
self.ind_col = indicatif
|
||||||
|
|
||||||
def get_identity(self):
|
def get_identity(self) -> str:
|
||||||
"""
|
"""
|
||||||
Calcul le nom/prénom de l'étudiant (données ScoDoc en priorité, sinon données Apogée)
|
Calcule le nom/prénom de l'étudiant (données ScoDoc en priorité, sinon données Apogée)
|
||||||
:return: L'identité calculée
|
:return: L'identité calculée
|
||||||
"""
|
"""
|
||||||
if self.data_scodoc is not None:
|
if self.data_scodoc is not None:
|
||||||
@ -176,9 +181,12 @@ class DataEtudiant(object):
|
|||||||
|
|
||||||
def _help() -> str:
|
def _help() -> str:
|
||||||
return """
|
return """
|
||||||
<div id="export_help" class="pas_help"> <span>Explications sur les tableaux des effectifs et liste des
|
<div id="export_help" class="pas_help">
|
||||||
étudiants</span>
|
<span>Explications sur les tableaux des effectifs
|
||||||
<div> <p>Le tableau des effectifs présente le nombre d'étudiants selon deux critères:</p>
|
et liste des étudiants</span>
|
||||||
|
<div>
|
||||||
|
<p>Le tableau des effectifs présente le nombre d'étudiants selon deux critères:
|
||||||
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>En colonne le statut de l'étudiant par rapport à Apogée:
|
<li>En colonne le statut de l'étudiant par rapport à Apogée:
|
||||||
<ul>
|
<ul>
|
||||||
@ -406,7 +414,8 @@ class EtapeBilan:
|
|||||||
for key_etape in self.etapes:
|
for key_etape in self.etapes:
|
||||||
annee_apogee, etapestr = key_to_values(key_etape)
|
annee_apogee, etapestr = key_to_values(key_etape)
|
||||||
self.etu_etapes[key_etape] = set()
|
self.etu_etapes[key_etape] = set()
|
||||||
for etud in get_inscrits_etape(etapestr, annee_apogee):
|
# get_inscrits_etape interroge portail Apo:
|
||||||
|
for etud in sco_portal_apogee.get_inscrits_etape(etapestr, annee_apogee):
|
||||||
key_etu = self.register_etud_apogee(etud, key_etape)
|
key_etu = self.register_etud_apogee(etud, key_etape)
|
||||||
self.etu_etapes[key_etape].add(key_etu)
|
self.etu_etapes[key_etape].add(key_etu)
|
||||||
|
|
||||||
@ -444,7 +453,6 @@ class EtapeBilan:
|
|||||||
data_etu = self.etudiants[key_etu]
|
data_etu = self.etudiants[key_etu]
|
||||||
ind_col = "-"
|
ind_col = "-"
|
||||||
ind_row = "-"
|
ind_row = "-"
|
||||||
|
|
||||||
# calcul de la colonne
|
# calcul de la colonne
|
||||||
if len(data_etu.etapes) == 1:
|
if len(data_etu.etapes) == 1:
|
||||||
ind_col = self.indicatifs[list(data_etu.etapes)[0]]
|
ind_col = self.indicatifs[list(data_etu.etapes)[0]]
|
||||||
@ -478,32 +486,34 @@ class EtapeBilan:
|
|||||||
affichage de l'html
|
affichage de l'html
|
||||||
:return: Le code html à afficher
|
:return: Le code html à afficher
|
||||||
"""
|
"""
|
||||||
|
if not sco_portal_apogee.has_portal():
|
||||||
|
return """<div id="synthese" class="semset_description">
|
||||||
|
<em>Pas de portail Apogée configuré</em>
|
||||||
|
</div>"""
|
||||||
self.load_listes() # chargement des données
|
self.load_listes() # chargement des données
|
||||||
self.dispatch() # analyse et répartition
|
self.dispatch() # analyse et répartition
|
||||||
# calcul de la liste des colonnes et des lignes de la table des effectifs
|
# calcul de la liste des colonnes et des lignes de la table des effectifs
|
||||||
self.all_rows_str = "'" + ",".join(["." + r for r in self.all_rows_ind]) + "'"
|
self.all_rows_str = "'" + ",".join(["." + r for r in self.all_rows_ind]) + "'"
|
||||||
self.all_cols_str = "'" + ",".join(["." + c for c in self.all_cols_ind]) + "'"
|
self.all_cols_str = "'" + ",".join(["." + c for c in self.all_cols_ind]) + "'"
|
||||||
|
|
||||||
H = [
|
return f"""
|
||||||
"""<div id="synthese" class="semset_description">
|
<div id="synthese" class="semset_description">
|
||||||
<details open="true">
|
<details open="true">
|
||||||
<summary><b>Tableau des effectifs</b>
|
<summary><b>Tableau des effectifs</b>
|
||||||
</summary>
|
</summary>
|
||||||
""",
|
{self._diagtable()}
|
||||||
self._diagtable(),
|
</details>
|
||||||
"""</details>""",
|
{self.display_tags()}
|
||||||
self.display_tags(),
|
<details open="true">
|
||||||
"""<details open="true">
|
<summary>
|
||||||
<summary><b id="effectifs">Liste des étudiants <span id="compte"></span></b>
|
<b id="effectifs">Liste des étudiants <span id="compte"></span></b>
|
||||||
</summary>
|
</summary>
|
||||||
""",
|
{entete_liste_etudiant()}
|
||||||
entete_liste_etudiant(),
|
{self.table_effectifs()}
|
||||||
self.table_effectifs(),
|
</details>
|
||||||
"""</details>""",
|
{_help()}
|
||||||
_help(),
|
</div>
|
||||||
]
|
"""
|
||||||
|
|
||||||
return "\n".join(H)
|
|
||||||
|
|
||||||
def _inc_count(self, ind_row, ind_col):
|
def _inc_count(self, ind_row, ind_col):
|
||||||
if (ind_row, ind_col) not in self.repartition:
|
if (ind_row, ind_col) not in self.repartition:
|
||||||
@ -692,26 +702,34 @@ class EtapeBilan:
|
|||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def link_etu(etudid, nom):
|
def link_etu(etudid, nom) -> str:
|
||||||
return '<a class="stdlink" href="%s">%s</a>' % (
|
"Lien html vers fiche de l'étudiant"
|
||||||
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid),
|
return f"""<a class="stdlink" href="{
|
||||||
nom,
|
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
|
||||||
)
|
}">{nom}</a>"""
|
||||||
|
|
||||||
def link_semestre(self, semestre, short=False):
|
def link_semestre(self, semestre, short=False) -> str:
|
||||||
if short:
|
"Lien html vers tableau de bord semestre"
|
||||||
return (
|
key = "session_id" if short else "titremois"
|
||||||
'<a class="stdlink" href="formsemestre_status?formsemestre_id=%(formsemestre_id)s">%('
|
sem = self.semestres[semestre]
|
||||||
"formsemestre_id)s</a> " % self.semestres[semestre]
|
return f"""<a class="stdlink" href="{
|
||||||
)
|
url_for("notes.formsemestre_status", scodoc_dept=g.scodoc_dept,
|
||||||
else:
|
formsemestre_id=sem['formsemestre_id']
|
||||||
return (
|
)}">{sem[key]}</a>
|
||||||
'<a class="stdlink" href="formsemestre_status?formsemestre_id=%(formsemestre_id)s">%(titre_num)s'
|
"""
|
||||||
" %(mois_debut)s - %(mois_fin)s)</a>" % self.semestres[semestre]
|
|
||||||
)
|
|
||||||
|
|
||||||
def table_effectifs(self):
|
def table_effectifs(self) -> str:
|
||||||
H = []
|
"Table html donnant les étudiants dans chaque semestre"
|
||||||
|
H = [
|
||||||
|
"""
|
||||||
|
<style>
|
||||||
|
table#apo-detail td.semestre {
|
||||||
|
white-space: nowrap;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
"""
|
||||||
|
]
|
||||||
|
|
||||||
col_ids = ["tag", "etudiant", "prenom", "nip", "semestre", "apogee", "annee"]
|
col_ids = ["tag", "etudiant", "prenom", "nip", "semestre", "apogee", "annee"]
|
||||||
titles = {
|
titles = {
|
||||||
@ -766,6 +784,7 @@ class EtapeBilan:
|
|||||||
titles,
|
titles,
|
||||||
html_class="table_leftalign",
|
html_class="table_leftalign",
|
||||||
html_sortable=True,
|
html_sortable=True,
|
||||||
|
html_with_td_classes=True,
|
||||||
table_id="apo-detail",
|
table_id="apo-detail",
|
||||||
).gen(fmt="html")
|
).gen(fmt="html")
|
||||||
)
|
)
|
||||||
|
@ -143,6 +143,7 @@ def formation_export_dict(
|
|||||||
|
|
||||||
if not export_codes_apo:
|
if not export_codes_apo:
|
||||||
ue_dict.pop("code_apogee", None)
|
ue_dict.pop("code_apogee", None)
|
||||||
|
ue_dict.pop("code_apogee_rcue", None)
|
||||||
if ue_dict.get("ects") is None:
|
if ue_dict.get("ects") is None:
|
||||||
ue_dict.pop("ects", None)
|
ue_dict.pop("ects", None)
|
||||||
mats = sco_edit_matiere.matiere_list({"ue_id": ue.id})
|
mats = sco_edit_matiere.matiere_list({"ue_id": ue.id})
|
||||||
|
@ -419,49 +419,23 @@ def sem_set_responsable_name(sem):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def sem_in_semestre_scolaire(
|
def sem_in_annee_scolaire(sem: dict, year=False): # OBSOLETE
|
||||||
sem,
|
|
||||||
year=False,
|
|
||||||
periode=None,
|
|
||||||
mois_pivot_annee=scu.MONTH_DEBUT_ANNEE_SCOLAIRE,
|
|
||||||
mois_pivot_periode=scu.MONTH_DEBUT_PERIODE2,
|
|
||||||
) -> bool:
|
|
||||||
"""Vrai si la date du début du semestre est dans la période indiquée (1,2,0)
|
|
||||||
du semestre `periode` de l'année scolaire indiquée
|
|
||||||
(ou, à défaut, de celle en cours).
|
|
||||||
|
|
||||||
La période utilise les même conventions que semset["sem_id"];
|
|
||||||
* 1 : première période
|
|
||||||
* 2 : deuxième période
|
|
||||||
* 0 ou période non précisée: annualisé (donc inclut toutes les périodes)
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
if not year:
|
|
||||||
year = scu.annee_scolaire()
|
|
||||||
# n'utilise pas le jour pivot
|
|
||||||
jour_pivot_annee = jour_pivot_periode = 1
|
|
||||||
# calcule l'année universitaire et la période
|
|
||||||
sem_annee, sem_periode = FormSemestre.comp_periode(
|
|
||||||
datetime.datetime.fromisoformat(sem["date_debut_iso"]),
|
|
||||||
mois_pivot_annee,
|
|
||||||
mois_pivot_periode,
|
|
||||||
jour_pivot_annee,
|
|
||||||
jour_pivot_periode,
|
|
||||||
)
|
|
||||||
if periode is None or periode == 0:
|
|
||||||
return sem_annee == year
|
|
||||||
return sem_annee == year and sem_periode == periode
|
|
||||||
|
|
||||||
|
|
||||||
def sem_in_annee_scolaire(sem, year=False):
|
|
||||||
"""Test si sem appartient à l'année scolaire year (int).
|
"""Test si sem appartient à l'année scolaire year (int).
|
||||||
N'utilise que la date de début, pivot au 1er août.
|
N'utilise que la date de début, pivot au 1er août.
|
||||||
Si année non specifiée, année scolaire courante
|
Si année non specifiée, année scolaire courante
|
||||||
"""
|
"""
|
||||||
return sem_in_semestre_scolaire(sem, year, periode=0)
|
return FormSemestre.est_in_semestre_scolaire(
|
||||||
|
datetime.date.fromisoformat(sem["date_debut_iso"]), year, periode=0
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def sem_est_courant(sem): # -> FormSemestre.est_courant
|
def sem_in_semestre_scolaire(sem, year=False, periode=None): # OBSOLETE
|
||||||
|
return FormSemestre.est_in_semestre_scolaire(
|
||||||
|
datetime.date.fromisoformat(sem["date_debut_iso"]), year, periode=periode
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def sem_est_courant(sem: dict): # -> FormSemestre.est_courant
|
||||||
"""Vrai si la date actuelle (now) est dans le semestre (les dates de début et fin sont incluses)"""
|
"""Vrai si la date actuelle (now) est dans le semestre (les dates de début et fin sont incluses)"""
|
||||||
now = time.strftime("%Y-%m-%d")
|
now = time.strftime("%Y-%m-%d")
|
||||||
debut = ndb.DateDMYtoISO(sem["date_debut"])
|
debut = ndb.DateDMYtoISO(sem["date_debut"])
|
||||||
|
@ -438,12 +438,13 @@ def do_formsemestre_createwithmodules(edit=False, formsemestre: FormSemestre = N
|
|||||||
"elt_sem_apo",
|
"elt_sem_apo",
|
||||||
{
|
{
|
||||||
"size": 32,
|
"size": 32,
|
||||||
"title": "Element(s) Apogée:",
|
"title": "Element(s) Apogée sem.:",
|
||||||
"explanation": "associé(s) au résultat du semestre (ex: VRTW1). Inutile en BUT. Séparés par des virgules.",
|
"explanation": "associé(s) au résultat du semestre (ex: VRTW1). Inutile en BUT. Séparés par des virgules.",
|
||||||
"allow_null": not sco_preferences.get_preference(
|
"allow_null": not sco_preferences.get_preference(
|
||||||
"always_require_apo_sem_codes"
|
"always_require_apo_sem_codes"
|
||||||
)
|
)
|
||||||
or (formsemestre and formsemestre.modalite == "EXT"),
|
or (formsemestre and formsemestre.modalite == "EXT")
|
||||||
|
or (formsemestre.formation.is_apc()),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -452,7 +453,7 @@ def do_formsemestre_createwithmodules(edit=False, formsemestre: FormSemestre = N
|
|||||||
"elt_annee_apo",
|
"elt_annee_apo",
|
||||||
{
|
{
|
||||||
"size": 32,
|
"size": 32,
|
||||||
"title": "Element(s) Apogée:",
|
"title": "Element(s) Apogée année:",
|
||||||
"explanation": "associé(s) au résultat de l'année (ex: VRT1A). Séparés par des virgules.",
|
"explanation": "associé(s) au résultat de l'année (ex: VRT1A). Séparés par des virgules.",
|
||||||
"allow_null": not sco_preferences.get_preference(
|
"allow_null": not sco_preferences.get_preference(
|
||||||
"always_require_apo_sem_codes"
|
"always_require_apo_sem_codes"
|
||||||
|
@ -381,7 +381,6 @@ class SemSet(dict):
|
|||||||
(actif seulement si un portail est configuré)
|
(actif seulement si un portail est configuré)
|
||||||
"""
|
"""
|
||||||
return self.bilan.html_diagnostic()
|
return self.bilan.html_diagnostic()
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def get_semsets_list():
|
def get_semsets_list():
|
||||||
|
@ -4165,6 +4165,11 @@ div.apo_csv_list {
|
|||||||
border: 1px dashed rgb(150, 10, 40);
|
border: 1px dashed rgb(150, 10, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table#apo_csv_list td {
|
||||||
|
white-space: nowrap;
|
||||||
|
word-break: no-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
#apo_csv_download {
|
#apo_csv_download {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user