Element de passage dans apogée. Close #937

This commit is contained in:
Emmanuel Viennet 2024-06-26 21:26:51 +02:00
parent c2a248633f
commit 34aab0a46f
3 changed files with 54 additions and 19 deletions

View File

@ -221,7 +221,8 @@ class ApoEtud(dict):
except KeyError as exc: except KeyError as exc:
raise ScoFormatError( raise ScoFormatError(
f"""Fichier Apogee invalide : ligne mal formatée ? <br>colonne <tt>{ f"""Fichier Apogee invalide : ligne mal formatée ? <br>colonne <tt>{
col_id}</tt> non déclarée ?""" col_id}</tt> non déclarée ?""",
safe=True,
) from exc ) from exc
else: else:
try: try:
@ -326,9 +327,14 @@ class ApoEtud(dict):
self.log.append("export étape désactivé") self.log.append("export étape désactivé")
return VOID_APO_RES return VOID_APO_RES
# Element passage
res_passage = self.search_elt_passage(code, res)
if res_passage:
return res_passage
# Elements UE # Elements UE
res_ue = self.search_elt_ue(code, res) res_ue = self.search_elt_ue(code, res)
if res_ue != {}: if res_ue:
return res_ue return res_ue
# Elements Modules # Elements Modules
@ -403,6 +409,25 @@ class ApoEtud(dict):
return VOID_APO_RES return VOID_APO_RES
return {} # no UE result found for this code return {} # no UE result found for this code
def search_elt_passage(self, code: str, res: NotesTableCompat) -> dict:
"""Cherche un résultat de type "passage" pour ce code Apogée.
dict vide si pas de résultat trouvé pour ce code.
L'élement est rempli si:
- code est dans les codes passage du formsemestre (sem)
- autorisation d'inscription enregistre de sem vers sem d'indice suivant
"""
if res.formsemestre.semestre_id < 1:
return {}
next_semestre_id = res.formsemestre.semestre_id + 1
if code in res.formsemestre.get_codes_apogee(category="passage"):
if next_semestre_id in res.get_autorisations_inscription().get(
self.etud.id, set()
):
return dict(
N="", B=20, J="", R=ScoDocSiteConfig.get_code_apo("ADM"), M=""
)
return {}
def comp_elt_semestre(self, nt: NotesTableCompat, decision: dict, etudid: int): def comp_elt_semestre(self, nt: NotesTableCompat, decision: dict, etudid: int):
"""Calcul résultat apo semestre. """Calcul résultat apo semestre.
Toujours vide pour en BUT/APC. Toujours vide pour en BUT/APC.
@ -703,7 +728,8 @@ class ApoData:
filename = self.orig_filename or e.filename filename = self.orig_filename or e.filename
raise ScoFormatError( raise ScoFormatError(
f"""<h3>Erreur lecture du fichier Apogée <tt>{filename}</tt></h3> f"""<h3>Erreur lecture du fichier Apogée <tt>{filename}</tt></h3>
<p>{e.args[0]}</p>""" <p>{e.args[0]}</p>""",
safe=True,
) from e ) from e
self.etape_apogee = self.get_etape_apogee() # 'V1RT' self.etape_apogee = self.get_etape_apogee() # 'V1RT'
self.vdi_apogee = self.get_vdi_apogee() # '111' self.vdi_apogee = self.get_vdi_apogee() # '111'
@ -795,7 +821,9 @@ class ApoData:
self.sems_periode = None self.sems_periode = None
def get_etape_apogee(self) -> str: def get_etape_apogee(self) -> str:
"""Le code etape: 'V1RT', donné par le code de l'élément VET""" """Le code etape: 'V1RT', donné par le code de l'élément VET.
Le VET doit être parmi les colonnes de la section XX-APO_COLONNES-XX
"""
for elt in self.apo_csv.apo_elts.values(): for elt in self.apo_csv.apo_elts.values():
if elt.type_objet == "VET": if elt.type_objet == "VET":
return elt.code return elt.code
@ -860,7 +888,8 @@ class ApoData:
log(f"Colonnes presentes: {present}") log(f"Colonnes presentes: {present}")
raise ScoFormatError( raise ScoFormatError(
f"""Fichier Apogee invalide<br>Colonnes declarees: <tt>{declared}</tt> f"""Fichier Apogee invalide<br>Colonnes declarees: <tt>{declared}</tt>
<br>Colonnes presentes: <tt>{present}</tt>""" <br>Colonnes presentes: <tt>{present}</tt>""",
safe=True,
) from exc ) from exc
# l'ensemble de tous les codes des elements apo des semestres: # l'ensemble de tous les codes des elements apo des semestres:
sem_elems = reduce(set.union, list(self.get_codes_by_sem().values()), set()) sem_elems = reduce(set.union, list(self.get_codes_by_sem().values()), set())

View File

@ -299,11 +299,14 @@ class ApoCSVReadWrite:
for i, field in enumerate(fields): for i, field in enumerate(fields):
cols[self.col_ids[i]] = field cols[self.col_ids[i]] = field
except IndexError as exc: except IndexError as exc:
raise
raise ScoFormatError( raise ScoFormatError(
f"Fichier Apogee incorrect (colonnes excédentaires ? (<tt>{i}/{field}</tt>))", f"Fichier Apogee incorrect (colonnes excédentaires ? (<tt>{i}/{field}</tt>))",
filename=self.get_filename(), filename=self.get_filename(),
safe=True,
) from exc ) from exc
# Ajoute colonnes vides manquantes, pratique si on a édité le fichier Apo à la main...
for i in range(len(fields), len(self.col_ids)):
cols[self.col_ids[i]] = ""
etud_tuples.append( etud_tuples.append(
ApoEtudTuple( ApoEtudTuple(
nip=fields[0], # id etudiant nip=fields[0], # id etudiant
@ -337,6 +340,8 @@ class ApoCSVReadWrite:
fields = line.split(APO_SEP) fields = line.split(APO_SEP)
if len(fields) == 2: if len(fields) == 2:
k, v = fields k, v = fields
elif len(fields) == 1:
k, v = fields[0], ""
else: else:
log(f"Error read CSV: \nline={line}\nfields={fields}") log(f"Error read CSV: \nline={line}\nfields={fields}")
log(dir(f)) log(dir(f))

View File

@ -61,12 +61,12 @@ class ScoValueError(ScoException):
class ScoPermissionDenied(ScoValueError): class ScoPermissionDenied(ScoValueError):
"""Permission non accordée (appli web)""" """Permission non accordée (appli web)"""
def __init__(self, msg=None, dest_url=None): def __init__(self, msg=None, dest_url=None, safe=False):
if msg is None: if msg is None:
msg = f"""Opération non autorisée pour { msg = f"""Opération non autorisée pour {
current_user.get_nomcomplet() if current_user else "?" current_user.get_nomcomplet() if current_user else "?"
}. Pas la permission, ou objet verrouillé.""" }. Pas la permission, ou objet verrouillé."""
super().__init__(msg, dest_url=dest_url) super().__init__(msg, dest_url=dest_url, safe=safe)
class ScoBugCatcher(ScoException): class ScoBugCatcher(ScoException):
@ -84,8 +84,8 @@ class InvalidEtudId(NoteProcessError):
class ScoFormatError(ScoValueError): class ScoFormatError(ScoValueError):
"Erreur lecture d'un fichier fourni par l'utilisateur" "Erreur lecture d'un fichier fourni par l'utilisateur"
def __init__(self, msg, filename="", dest_url=None): def __init__(self, msg, filename="", dest_url=None, safe=False):
super().__init__(msg, dest_url=dest_url) super().__init__(msg, dest_url=dest_url, safe=safe)
self.filename = filename self.filename = filename
@ -95,15 +95,15 @@ class ScoInvalidParamError(ScoValueError):
(id strings, ...) (id strings, ...)
""" """
def __init__(self, msg=None, dest_url=None): def __init__(self, msg=None, dest_url=None, safe=False):
msg = msg or "Adresse invalide. Vérifiez vos signets." msg = msg or "Adresse invalide. Vérifiez vos signets."
super().__init__(msg, dest_url=dest_url) super().__init__(msg, dest_url=dest_url, safe=safe)
class ScoPDFFormatError(ScoValueError): class ScoPDFFormatError(ScoValueError):
"erreur génération PDF (templates platypus, ...)" "erreur génération PDF (templates platypus, ...)"
def __init__(self, msg, dest_url=None): def __init__(self, msg, dest_url=None, safe=False):
super().__init__( super().__init__(
f"""Erreur dans un format pdf: f"""Erreur dans un format pdf:
<p>{msg}</p> <p>{msg}</p>
@ -112,6 +112,7 @@ class ScoPDFFormatError(ScoValueError):
</p> </p>
""", """,
dest_url=dest_url, dest_url=dest_url,
safe=safe,
) )
@ -130,33 +131,33 @@ class ScoConfigurationError(ScoValueError):
class ScoLockedFormError(ScoValueError): class ScoLockedFormError(ScoValueError):
"Modification d'une formation verrouillée" "Modification d'une formation verrouillée"
def __init__(self, msg="", dest_url=None): def __init__(self, msg="", dest_url=None, safe=False):
msg = ( msg = (
"Cette formation est verrouillée (car il y a un semestre verrouillé qui s'y réfère). " "Cette formation est verrouillée (car il y a un semestre verrouillé qui s'y réfère). "
+ str(msg) + str(msg)
) )
super().__init__(msg=msg, dest_url=dest_url) super().__init__(msg=msg, dest_url=dest_url, safe=safe)
class ScoLockedSemError(ScoValueError): class ScoLockedSemError(ScoValueError):
"Modification d'un formsemestre verrouillé" "Modification d'un formsemestre verrouillé"
def __init__(self, msg="", dest_url=None): def __init__(self, msg="", dest_url=None, safe=False):
msg = "Ce semestre est verrouillé ! " + str(msg) msg = "Ce semestre est verrouillé ! " + str(msg)
super().__init__(msg=msg, dest_url=dest_url) super().__init__(msg=msg, dest_url=dest_url, safe=safe)
class ScoNonEmptyFormationObject(ScoValueError): class ScoNonEmptyFormationObject(ScoValueError):
"""On ne peut pas supprimer un module/matiere ou UE si des formsemestre s'y réfèrent""" """On ne peut pas supprimer un module/matiere ou UE si des formsemestre s'y réfèrent"""
def __init__(self, type_objet="objet'", msg="", dest_url=None): def __init__(self, type_objet="objet'", msg="", dest_url=None, safe=False):
msg = f"""<h3>{type_objet} "{msg}" utilisé(e) dans des semestres: suppression impossible.</h3> msg = f"""<h3>{type_objet} "{msg}" utilisé(e) dans des semestres: suppression impossible.</h3>
<p class="help">Il faut d'abord supprimer le semestre (ou en retirer ce {type_objet}). <p class="help">Il faut d'abord supprimer le semestre (ou en retirer ce {type_objet}).
Mais il est peut-être préférable de laisser ce programme intact et d'en créer une Mais il est peut-être préférable de laisser ce programme intact et d'en créer une
nouvelle version pour la modifier sans affecter les semestres déjà en place. nouvelle version pour la modifier sans affecter les semestres déjà en place.
</p> </p>
""" """
super().__init__(msg=msg, dest_url=dest_url) super().__init__(msg=msg, dest_url=dest_url, safe=safe)
class ScoInvalidIdType(ScoValueError): class ScoInvalidIdType(ScoValueError):