diff --git a/app/api/jury.py b/app/api/jury.py index d3a1d145..294eef2f 100644 --- a/app/api/jury.py +++ b/app/api/jury.py @@ -282,6 +282,8 @@ def validation_rcue_record(etudid: int): ) operation = "record" db.session.add(validation) + # invalider bulletins (les autres résultats ne dépendent pas des RCUEs): + sco_cache.invalidate_formsemestre_etud(etud) db.session.commit() Scolog.logdb( method="validation_rcue_record", diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py index a7b10195..be395fea 100644 --- a/app/models/formsemestre.py +++ b/app/models/formsemestre.py @@ -307,6 +307,17 @@ class FormSemestre(db.Model): - et sont associées à l'un des parcours de ce formsemestre (ou à aucun, donc tronc commun). """ + # per-request caching + key = (self.id, with_sport) + _cache = getattr(g, "_formsemestre_get_ues_cache", None) + if _cache: + result = _cache.get(key, False) + if result is not False: + return result + else: + g._formsemestre_get_ues_cache = {} + _cache = g._formsemestre_get_ues_cache + formation: Formation = self.formation if formation.is_apc(): # UEs de tronc commun (sans parcours indiqué) @@ -326,8 +337,7 @@ class FormSemestre(db.Model): ).filter(UniteEns.semestre_idx == self.semestre_id) } ) - ues = sem_ues.values() - return sorted(ues, key=attrgetter("numero", "acronyme")) + ues = sorted(sem_ues.values(), key=attrgetter("numero", "acronyme")) else: sem_ues = db.session.query(UniteEns).filter( ModuleImpl.formsemestre_id == self.id, @@ -336,7 +346,9 @@ class FormSemestre(db.Model): ) if not with_sport: sem_ues = sem_ues.filter(UniteEns.type != codes_cursus.UE_SPORT) - return sem_ues.order_by(UniteEns.numero).all() + ues = sem_ues.order_by(UniteEns.numero).all() + _cache[key] = ues + return ues @cached_property def modimpls_sorted(self) -> list[ModuleImpl]: diff --git a/app/scodoc/sco_pv_dict.py b/app/scodoc/sco_pv_dict.py index f9861f54..e4e58ca1 100644 --- a/app/scodoc/sco_pv_dict.py +++ b/app/scodoc/sco_pv_dict.py @@ -63,25 +63,32 @@ def dict_pvjury( Si with_parcours_decisions: ajoute infos sur code decision jury de tous les semestre du parcours Résultat: { - 'date' : date de la decision la plus recente, - 'formsemestre' : sem, - 'is_apc' : bool, - 'formation' : { 'acronyme' :, 'titre': ... } - 'decisions' : { [ { 'identite' : {'nom' :, 'prenom':, ...,}, - 'etat' : I ou D ou DEF - 'decision_sem' : {'code':, 'code_prev': }, - 'decisions_ue' : { ue_id : { 'code' : ADM|CMP|AJ, 'event_date' :, - 'acronyme', 'numero': } }, - 'autorisations' : [ { 'semestre_id' : { ... } } ], - 'validation_parcours' : True si parcours validé (diplome obtenu) - 'prev_code' : code (calculé slt si with_prev), - 'mention' : mention (en fct moy gen), - 'sum_ects' : total ECTS acquis dans ce semestre (incluant les UE capitalisées) - 'sum_ects_capitalises' : somme des ECTS des UE capitalisees - } - ] - }, - 'decisions_dict' : { etudid : decision (comme ci-dessus) }, + 'date' : str = date de la decision la plus recente, format dd/mm/yyyy, + 'formsemestre' : dict = formsemestre, + 'is_apc' : bool, + 'formation' : { 'acronyme' :, 'titre': ... } + 'decisions' : [ + { + 'identite' : {'nom' :, 'prenom':, ...,}, + 'etat' : I ou D ou DEF + 'decision_sem' : {'code':, 'code_prev': }, + 'decisions_ue' : { + ue_id : { + 'code' : ADM|CMP|AJ, + 'ects' : float, + 'event_date' :str = "dd/mm/yyyy", + }, + }, + 'autorisations' : [ { 'semestre_id' : { ... } } ], + 'validation_parcours' : True si parcours validé (diplome obtenu) + 'prev_code' : code (calculé slt si with_prev), + 'mention' : mention (en fct moy gen), + 'sum_ects' : total ECTS acquis dans ce semestre (incluant les UE capitalisées) + 'sum_ects_capitalises' : somme des ECTS des UE capitalisees + }, + ... + ], + 'decisions_dict' : { etudid : decision (comme ci-dessus) }, } """ formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) diff --git a/app/static/css/partition_editor.css b/app/static/css/partition_editor.css index c74e3f27..4697bc99 100644 --- a/app/static/css/partition_editor.css +++ b/app/static/css/partition_editor.css @@ -106,7 +106,7 @@ body:not(.editionActivated) .editing { @keyframes boing { 100% { - transform: translateY(-20px) + transform: translateY(-20px); } } @@ -152,6 +152,7 @@ body.editionActivated .filtres>div>div>div>div { color: #000; border-radius: 4px; outline: 4px solid #FFF; + padding: 2px; } /* Suppression */ @@ -355,7 +356,7 @@ body.editionActivated .filtres .nonEditable .move { } .groupe:has(.etudiants:empty) { - display: none; + display: none; } /* .filtres .unselect { @@ -365,6 +366,23 @@ body.editionActivated .filtres .nonEditable .move { /*****************************/ /* Zone Etudiants */ /*****************************/ +#zoneChoix .autoAffectation>a { + text-decoration: underline; +} + +#zoneChoix .dropZone { + background: #FFF; + border-radius: 8px; + border: 2px dashed #09C; + margin-bottom: 4px; + padding: 4px; + transition: 0.2s; +} + +.fileOver { + transform: scale(0.9); +} + #zoneChoix>.autoAffectation { background: #c9c9c9; color: #141414; diff --git a/app/templates/scolar/partition_editor.j2 b/app/templates/scolar/partition_editor.j2 index d98d8dc1..82cca658 100644 --- a/app/templates/scolar/partition_editor.j2 +++ b/app/templates/scolar/partition_editor.j2 @@ -22,6 +22,23 @@

Étudiants

+
+ + + Aide à l'affectation dans les parcours +
Importer les résultats : +
+
+ Déposez le fichier .xlsx ou
+ +
+
+
+
Affecter automatiquement les étudiants du groupe
@@ -38,6 +55,7 @@
+ + \ No newline at end of file