forked from ScoDoc/ScoDoc
Page bilan ECTS etudiant toutes formations
This commit is contained in:
parent
d4fd6527e5
commit
abb6907a5d
@ -18,6 +18,7 @@ from collections.abc import Iterable
|
|||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
|
||||||
from flask import g, url_for
|
from flask import g, url_for
|
||||||
|
from flask_sqlalchemy.query import Query
|
||||||
|
|
||||||
from app import db, log
|
from app import db, log
|
||||||
from app.comp.res_but import ResultatsSemestreBUT
|
from app.comp.res_but import ResultatsSemestreBUT
|
||||||
@ -393,6 +394,26 @@ def but_ects_valides(
|
|||||||
et ne les compte qu'une fois même en cas de redoublement avec re-validation.
|
et ne les compte qu'une fois même en cas de redoublement avec re-validation.
|
||||||
Si annees_but est spécifié, un iterable "BUT1, "BUT2" par exemple, ne prend que ces années.
|
Si annees_but est spécifié, un iterable "BUT1, "BUT2" par exemple, ne prend que ces années.
|
||||||
"""
|
"""
|
||||||
|
validations = but_validations_ues(etud, referentiel_competence_id, annees_but)
|
||||||
|
ects_dict = {}
|
||||||
|
for v in validations:
|
||||||
|
key = (v.ue.semestre_idx, v.ue.niveau_competence.id)
|
||||||
|
if v.code in CODES_UE_VALIDES:
|
||||||
|
ects_dict[key] = v.ue.ects
|
||||||
|
|
||||||
|
return int(sum(ects_dict.values())) if ects_dict else 0
|
||||||
|
|
||||||
|
|
||||||
|
def but_validations_ues(
|
||||||
|
etud: Identite,
|
||||||
|
referentiel_competence_id: int,
|
||||||
|
annees_but: None | Iterable[str] = None,
|
||||||
|
) -> Query:
|
||||||
|
"""Query les validations d'UEs pour cet étudiant
|
||||||
|
dans des UEs appartenant à ce référentiel de compétence
|
||||||
|
et en option pour les années BUT indiquées.
|
||||||
|
annees_but : None (tout) ou liste [ "BUT1", ... ]
|
||||||
|
"""
|
||||||
validations = (
|
validations = (
|
||||||
ScolarFormSemestreValidation.query.filter_by(etudid=etud.id)
|
ScolarFormSemestreValidation.query.filter_by(etudid=etud.id)
|
||||||
.filter(ScolarFormSemestreValidation.ue_id != None)
|
.filter(ScolarFormSemestreValidation.ue_id != None)
|
||||||
@ -403,18 +424,10 @@ def but_ects_valides(
|
|||||||
if annees_but:
|
if annees_but:
|
||||||
validations = validations.filter(ApcNiveau.annee.in_(annees_but))
|
validations = validations.filter(ApcNiveau.annee.in_(annees_but))
|
||||||
# Et restreint au référentiel de compétence:
|
# Et restreint au référentiel de compétence:
|
||||||
validations = validations.join(ApcCompetence).filter_by(
|
return validations.join(ApcCompetence).filter_by(
|
||||||
referentiel_id=referentiel_competence_id
|
referentiel_id=referentiel_competence_id
|
||||||
)
|
)
|
||||||
|
|
||||||
ects_dict = {}
|
|
||||||
for v in validations:
|
|
||||||
key = (v.ue.semestre_idx, v.ue.niveau_competence.id)
|
|
||||||
if v.code in CODES_UE_VALIDES:
|
|
||||||
ects_dict[key] = v.ue.ects
|
|
||||||
|
|
||||||
return int(sum(ects_dict.values())) if ects_dict else 0
|
|
||||||
|
|
||||||
|
|
||||||
def etud_ues_de_but1_non_validees(
|
def etud_ues_de_but1_non_validees(
|
||||||
etud: Identite, formation: Formation, parcour: ApcParcours
|
etud: Identite, formation: Formation, parcour: ApcParcours
|
||||||
|
@ -845,11 +845,11 @@ class FormSemestre(models.ScoDocModel):
|
|||||||
else:
|
else:
|
||||||
return ", ".join([u.get_nomcomplet() for u in self.responsables])
|
return ", ".join([u.get_nomcomplet() for u in self.responsables])
|
||||||
|
|
||||||
def est_responsable(self, user: User):
|
def est_responsable(self, user: User) -> bool:
|
||||||
"True si l'user est l'un des responsables du semestre"
|
"True si l'user est l'un des responsables du semestre"
|
||||||
return user.id in [u.id for u in self.responsables]
|
return user.id in [u.id for u in self.responsables]
|
||||||
|
|
||||||
def est_chef_or_diretud(self, user: User = None):
|
def est_chef_or_diretud(self, user: User | None = None) -> bool:
|
||||||
"Vrai si utilisateur (par def. current) est admin, chef dept ou responsable du semestre"
|
"Vrai si utilisateur (par def. current) est admin, chef dept ou responsable du semestre"
|
||||||
user = user or current_user
|
user = user or current_user
|
||||||
return user.has_permission(Permission.EditFormSemestre) or self.est_responsable(
|
return user.has_permission(Permission.EditFormSemestre) or self.est_responsable(
|
||||||
@ -867,7 +867,7 @@ class FormSemestre(models.ScoDocModel):
|
|||||||
return True # typiquement admin, chef dept
|
return True # typiquement admin, chef dept
|
||||||
return self.est_responsable(user)
|
return self.est_responsable(user)
|
||||||
|
|
||||||
def can_edit_jury(self, user: User = None):
|
def can_edit_jury(self, user: User | None = None):
|
||||||
"""Vrai si utilisateur (par def. current) peut saisir decision de jury
|
"""Vrai si utilisateur (par def. current) peut saisir decision de jury
|
||||||
dans ce semestre: vérifie permission et verrouillage.
|
dans ce semestre: vérifie permission et verrouillage.
|
||||||
"""
|
"""
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
"""Notes, décisions de jury
|
"""Notes, décisions de jury
|
||||||
"""
|
"""
|
||||||
|
from flask_sqlalchemy.query import Query
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app import log
|
from app import log
|
||||||
from app.models import SHORT_STR_LEN
|
from app.models import SHORT_STR_LEN
|
||||||
from app.models import CODE_STR_LEN
|
from app.models import CODE_STR_LEN
|
||||||
from app.models.events import Scolog
|
from app.models.events import Scolog
|
||||||
|
from app.models.formations import Formation
|
||||||
|
from app.models.ues import UniteEns
|
||||||
from app.scodoc import sco_cache
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc.codes_cursus import CODES_UE_VALIDES
|
from app.scodoc.codes_cursus import CODES_UE_VALIDES
|
||||||
@ -113,6 +116,7 @@ class ScolarFormSemestreValidation(db.Model):
|
|||||||
if self.ue.parcours else ""}
|
if self.ue.parcours else ""}
|
||||||
{("émise par " + link)}
|
{("émise par " + link)}
|
||||||
: <b>{self.code}</b>{moyenne}
|
: <b>{self.code}</b>{moyenne}
|
||||||
|
<b>{self.ue.ects:g} ECTS</b>
|
||||||
le {self.event_date.strftime(scu.DATEATIME_FMT)}
|
le {self.event_date.strftime(scu.DATEATIME_FMT)}
|
||||||
"""
|
"""
|
||||||
else:
|
else:
|
||||||
@ -131,6 +135,27 @@ class ScolarFormSemestreValidation(db.Model):
|
|||||||
else 0.0
|
else 0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validations_ues(
|
||||||
|
cls, etud: "Identite", formation_code: str | None = None
|
||||||
|
) -> Query:
|
||||||
|
"""Query les validations d'UE pour cet étudiant dans des UEs de formations
|
||||||
|
du code indiqué, ou toutes si le formation_code est None.
|
||||||
|
"""
|
||||||
|
from app.models.formsemestre import FormSemestre
|
||||||
|
|
||||||
|
query = (
|
||||||
|
ScolarFormSemestreValidation.query.filter_by(etudid=etud.id)
|
||||||
|
.filter(ScolarFormSemestreValidation.ue_id != None)
|
||||||
|
.join(UniteEns)
|
||||||
|
.join(FormSemestre, ScolarFormSemestreValidation.formsemestre)
|
||||||
|
)
|
||||||
|
if formation_code is not None:
|
||||||
|
query = query.join(Formation).filter_by(formation_code=formation_code)
|
||||||
|
return query.order_by(
|
||||||
|
FormSemestre.semestre_id, UniteEns.numero, UniteEns.acronyme
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ScolarAutorisationInscription(db.Model):
|
class ScolarAutorisationInscription(db.Model):
|
||||||
"""Autorisation d'inscription dans un semestre"""
|
"""Autorisation d'inscription dans un semestre"""
|
||||||
|
@ -31,7 +31,7 @@ import time
|
|||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import url_for, flash, g, request
|
from flask import url_for, flash, g, request
|
||||||
from flask_login import current_user
|
from flask.templating import render_template
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from app.models import Identite, Evaluation
|
from app.models import Identite, Evaluation
|
||||||
@ -64,7 +64,6 @@ from app.scodoc import sco_cursus_dut
|
|||||||
from app.scodoc.sco_cursus_dut import etud_est_inscrit_ue
|
from app.scodoc.sco_cursus_dut import etud_est_inscrit_ue
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_pv_dict
|
from app.scodoc import sco_pv_dict
|
||||||
from app.scodoc.sco_permissions import Permission
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------------
|
||||||
@ -1249,7 +1248,7 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
|
|||||||
<p>On ne peut valider ici que les UEs du cursus <b>{formation.titre}</b></p>
|
<p>On ne peut valider ici que les UEs du cursus <b>{formation.titre}</b></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{_get_etud_ue_cap_html(etud, formsemestre)}
|
{_get_etud_ue_validations_html(etud, formsemestre)}
|
||||||
|
|
||||||
<div class="scobox">
|
<div class="scobox">
|
||||||
<div class="scobox-title">
|
<div class="scobox-title">
|
||||||
@ -1300,7 +1299,7 @@ def formsemestre_validate_previous_ue(formsemestre: FormSemestre, etud: Identite
|
|||||||
return flask.redirect(dest_url)
|
return flask.redirect(dest_url)
|
||||||
|
|
||||||
|
|
||||||
def _get_etud_ue_cap_html(etud: Identite, formsemestre: FormSemestre) -> str:
|
def _get_etud_ue_validations_html(etud: Identite, formsemestre: FormSemestre) -> str:
|
||||||
"""HTML listant les validations d'UEs pour cet étudiant dans des formations de même
|
"""HTML listant les validations d'UEs pour cet étudiant dans des formations de même
|
||||||
code que celle du formsemestre indiqué.
|
code que celle du formsemestre indiqué.
|
||||||
"""
|
"""
|
||||||
@ -1319,39 +1318,13 @@ def _get_etud_ue_cap_html(etud: Identite, formsemestre: FormSemestre) -> str:
|
|||||||
|
|
||||||
if not validations:
|
if not validations:
|
||||||
return ""
|
return ""
|
||||||
H = [
|
return render_template(
|
||||||
f"""<div class="sco_box sco_lightgreen_bg ue_list_etud_validations">
|
"jury/ue_list_etud_validations.j2",
|
||||||
<div class="sco_box_title">Validations d'UEs dans cette formation</div>
|
edit_mode=True,
|
||||||
<div class="help">Liste de toutes les UEs validées par {etud.html_link_fiche()},
|
etud=etud,
|
||||||
sur des semestres ou déclarées comme "antérieures" (externes).
|
titre_boite="Validations d'UEs dans cette formation",
|
||||||
</div>
|
validations=validations,
|
||||||
<ul class="liste_validations">"""
|
)
|
||||||
]
|
|
||||||
for validation in validations:
|
|
||||||
if validation.formsemestre_id is None:
|
|
||||||
origine = " enregistrée d'un parcours antérieur (hors ScoDoc)"
|
|
||||||
else:
|
|
||||||
origine = f", du semestre {formsemestre.html_link_status()}"
|
|
||||||
if validation.semestre_id is not None:
|
|
||||||
origine += f" (<b>S{validation.semestre_id}</b>)"
|
|
||||||
H.append(f"""<li>{validation.html()}""")
|
|
||||||
if (validation.formsemestre and validation.formsemestre.can_edit_jury()) or (
|
|
||||||
current_user and current_user.has_permission(Permission.EtudInscrit)
|
|
||||||
):
|
|
||||||
H.append(
|
|
||||||
f"""
|
|
||||||
<form class="inline-form">
|
|
||||||
<button
|
|
||||||
data-v_id="{validation.id}" data-type="validation_ue" data-etudid="{etud.id}"
|
|
||||||
>effacer</button>
|
|
||||||
</form>
|
|
||||||
""",
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
H.append(scu.icontag("lock_img", border="0", title="Semestre verrouillé"))
|
|
||||||
H.append("</li>")
|
|
||||||
H.append("</ul></div>")
|
|
||||||
return "\n".join(H)
|
|
||||||
|
|
||||||
|
|
||||||
def do_formsemestre_validate_previous_ue(
|
def do_formsemestre_validate_previous_ue(
|
||||||
|
@ -121,14 +121,14 @@ def _menu_scolarite(
|
|||||||
"enabled": def_enabled,
|
"enabled": def_enabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Inscrire à un module optionnel (ou au sport)",
|
"title": "Désinscrire (en cas d'erreur)",
|
||||||
"endpoint": "notes.formsemestre_inscription_option",
|
"endpoint": "notes.formsemestre_desinscription",
|
||||||
"args": args,
|
"args": args,
|
||||||
"enabled": authuser.has_permission(Permission.EtudInscrit) and not locked,
|
"enabled": authuser.has_permission(Permission.EtudInscrit) and not locked,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Désinscrire (en cas d'erreur)",
|
"title": "Inscrire à un module optionnel (ou au sport)",
|
||||||
"endpoint": "notes.formsemestre_desinscription",
|
"endpoint": "notes.formsemestre_inscription_option",
|
||||||
"args": args,
|
"args": args,
|
||||||
"enabled": authuser.has_permission(Permission.EtudInscrit) and not locked,
|
"enabled": authuser.has_permission(Permission.EtudInscrit) and not locked,
|
||||||
},
|
},
|
||||||
@ -138,12 +138,6 @@ def _menu_scolarite(
|
|||||||
"args": args,
|
"args": args,
|
||||||
"enabled": formsemestre.can_edit_jury(),
|
"enabled": formsemestre.can_edit_jury(),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"title": "Inscrire à un autre semestre",
|
|
||||||
"endpoint": "notes.formsemestre_inscription_with_modules_form",
|
|
||||||
"args": {"etudid": etudid},
|
|
||||||
"enabled": authuser.has_permission(Permission.EtudInscrit),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"title": "Enregistrer un semestre effectué ailleurs",
|
"title": "Enregistrer un semestre effectué ailleurs",
|
||||||
"endpoint": "notes.formsemestre_ext_create_form",
|
"endpoint": "notes.formsemestre_ext_create_form",
|
||||||
@ -156,6 +150,12 @@ def _menu_scolarite(
|
|||||||
"args": args,
|
"args": args,
|
||||||
"enabled": authuser.has_permission(Permission.EditAllNotes),
|
"enabled": authuser.has_permission(Permission.EditAllNotes),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "Inscrire à un autre semestre",
|
||||||
|
"endpoint": "notes.formsemestre_inscription_with_modules_form",
|
||||||
|
"args": {"etudid": etudid},
|
||||||
|
"enabled": authuser.has_permission(Permission.EtudInscrit),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
return htmlutils.make_menu(
|
return htmlutils.make_menu(
|
||||||
@ -317,6 +317,12 @@ def fiche_etud(etudid=None):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
info["link_inscrire_ailleurs"] = ""
|
info["link_inscrire_ailleurs"] = ""
|
||||||
|
info[
|
||||||
|
"link_bilan_ects"
|
||||||
|
] = f"""<span class="link_bul_pdf"><a class="stdlink" href="{
|
||||||
|
url_for("notes.etud_bilan_ects",
|
||||||
|
scodoc_dept=g.scodoc_dept, etudid=etudid)
|
||||||
|
}">ECTS</a></span>"""
|
||||||
else:
|
else:
|
||||||
# non inscrit
|
# non inscrit
|
||||||
l = [f"""<p><b>Étudiant{etud.e} non inscrit{etud.e}"""]
|
l = [f"""<p><b>Étudiant{etud.e} non inscrit{etud.e}"""]
|
||||||
@ -331,6 +337,7 @@ def fiche_etud(etudid=None):
|
|||||||
info["liste_inscriptions"] = "\n".join(l)
|
info["liste_inscriptions"] = "\n".join(l)
|
||||||
info["link_bul_pdf"] = ""
|
info["link_bul_pdf"] = ""
|
||||||
info["link_inscrire_ailleurs"] = ""
|
info["link_inscrire_ailleurs"] = ""
|
||||||
|
info["link_bilan_ects"] = ""
|
||||||
|
|
||||||
# Liste des annotations
|
# Liste des annotations
|
||||||
html_annotations_list = "\n".join(
|
html_annotations_list = "\n".join(
|
||||||
@ -433,7 +440,9 @@ def fiche_etud(etudid=None):
|
|||||||
"inscriptions_mkup"
|
"inscriptions_mkup"
|
||||||
] = f"""<div class="ficheinscriptions" id="ficheinscriptions">
|
] = f"""<div class="ficheinscriptions" id="ficheinscriptions">
|
||||||
<div class="fichetitre">Cursus</div>{info["liste_inscriptions"]}
|
<div class="fichetitre">Cursus</div>{info["liste_inscriptions"]}
|
||||||
{info["link_bul_pdf"]} {info["link_inscrire_ailleurs"]}
|
{info["link_bul_pdf"]}
|
||||||
|
{info["link_inscrire_ailleurs"]}
|
||||||
|
{info["link_bilan_ects"]}
|
||||||
</div>"""
|
</div>"""
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -246,7 +246,7 @@ PREF_CATEGORIES = (
|
|||||||
"bul_margins",
|
"bul_margins",
|
||||||
{
|
{
|
||||||
"title": "Marges additionnelles des bulletins, en millimètres",
|
"title": "Marges additionnelles des bulletins, en millimètres",
|
||||||
"subtitle": """Le bulletin de notes notes est toujours redimensionné
|
"subtitle": """Le bulletin de notes classique (pas BUT) est toujours redimensionné
|
||||||
pour occuper l'espace disponible entre les marges.
|
pour occuper l'espace disponible entre les marges.
|
||||||
""",
|
""",
|
||||||
"related": ("bul", "bul_mail", "pdf"),
|
"related": ("bul", "bul_mail", "pdf"),
|
||||||
|
@ -9,4 +9,10 @@ span.parcours {
|
|||||||
|
|
||||||
div.ue_list_etud_validations ul.liste_validations li {
|
div.ue_list_etud_validations ul.liste_validations li {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.ue_list_etud_validations div.total_ects {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: 12px;
|
||||||
}
|
}
|
24
app/templates/jury/etud_bilan_ects.j2
Normal file
24
app/templates/jury/etud_bilan_ects.j2
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends "sco_page.j2" %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<link href="{{scu.STATIC_DIR}}/css/jury_delete_manual.css" rel="stylesheet" type="text/css" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h1>Bilan des ECTS de {{etud.html_link_fiche()|safe}}</h1>
|
||||||
|
|
||||||
|
<div class="help">
|
||||||
|
Cette page donne toutes les UEs acquises par l'étudiant (codes <tt>ADM, ADJ, ADJR, ADSUP, CMP...</tt>)
|
||||||
|
dans chaque formation qu'il a suivi.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% for diplome in formsemestre_by_diplome %}
|
||||||
|
{% set titre_boite = "Validations d'UEs dans la formation " + titre_by_diplome[diplome] %}
|
||||||
|
{% set validations = validations_by_diplome[diplome] %}
|
||||||
|
{% set total_ects = ects_by_diplome[diplome] %}
|
||||||
|
{% include "jury/ue_list_etud_validations.j2" %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endblock app_content %}
|
31
app/templates/jury/ue_list_etud_validations.j2
Normal file
31
app/templates/jury/ue_list_etud_validations.j2
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{# Fragment de html pour cadre affichage validations d'une formation #}
|
||||||
|
|
||||||
|
<div class="sco_box sco_lightgreen_bg ue_list_etud_validations">
|
||||||
|
<div class="sco_box_title">{{titre_boite}}</div>
|
||||||
|
<div class="help">Liste de toutes les UEs validées par {{etud.html_link_fiche()|safe}},
|
||||||
|
sur des semestres ou déclarées comme "antérieures" (externes).
|
||||||
|
</div>
|
||||||
|
<ul class="liste_validations">
|
||||||
|
{% for validation in validations %}
|
||||||
|
|
||||||
|
<li>{{ validation.html() | safe }}
|
||||||
|
{% if edit_mode %}
|
||||||
|
{% if validation.formsemestre and validation.formsemestre.can_edit_jury() %}
|
||||||
|
<form class="inline-form">
|
||||||
|
<button data-v_id="{{validation.id}}" data-type="validation_ue" data-etudid="{{etud.id}}">
|
||||||
|
effacer
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
{{ scu.icontag("lock_img", border="0", title="Semestre verrouillé") }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% if total_ects %}
|
||||||
|
<div class="total_ects">
|
||||||
|
Total ECTS: {{ "%g" % total_ects }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
@ -27,7 +27,7 @@ Vues sur les jurys et validations
|
|||||||
|
|
||||||
Emmanuel Viennet, 2024
|
Emmanuel Viennet, 2024
|
||||||
"""
|
"""
|
||||||
|
from collections import defaultdict
|
||||||
import datetime
|
import datetime
|
||||||
import flask
|
import flask
|
||||||
from flask import flash, g, redirect, render_template, request, url_for
|
from flask import flash, g, redirect, render_template, request, url_for
|
||||||
@ -55,6 +55,7 @@ from app.models import (
|
|||||||
FormSemestreInscription,
|
FormSemestreInscription,
|
||||||
Identite,
|
Identite,
|
||||||
ScolarAutorisationInscription,
|
ScolarAutorisationInscription,
|
||||||
|
ScolarFormSemestreValidation,
|
||||||
ScolarNews,
|
ScolarNews,
|
||||||
ScoDocSiteConfig,
|
ScoDocSiteConfig,
|
||||||
)
|
)
|
||||||
@ -66,6 +67,7 @@ from app.scodoc import (
|
|||||||
sco_formsemestre_validation,
|
sco_formsemestre_validation,
|
||||||
sco_preferences,
|
sco_preferences,
|
||||||
)
|
)
|
||||||
|
from app.scodoc.codes_cursus import CODES_UE_VALIDES
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
from app.scodoc.sco_exceptions import (
|
from app.scodoc.sco_exceptions import (
|
||||||
ScoPermissionDenied,
|
ScoPermissionDenied,
|
||||||
@ -78,7 +80,6 @@ from app.scodoc.sco_pv_dict import descr_autorisations
|
|||||||
from app.views import notes_bp as bp
|
from app.views import notes_bp as bp
|
||||||
from app.views import ScoData
|
from app.views import ScoData
|
||||||
|
|
||||||
|
|
||||||
# --- FORMULAIRE POUR VALIDATION DES UE ET SEMESTRES
|
# --- FORMULAIRE POUR VALIDATION DES UE ET SEMESTRES
|
||||||
|
|
||||||
|
|
||||||
@ -902,3 +903,60 @@ def jury_delete_manual(etudid: int):
|
|||||||
"""Efface toute les décisions d'une année pour cet étudiant"""
|
"""Efface toute les décisions d'une année pour cet étudiant"""
|
||||||
etud = Identite.get_etud(etudid)
|
etud = Identite.get_etud(etudid)
|
||||||
return jury_edit_manual.jury_delete_manual(etud)
|
return jury_edit_manual.jury_delete_manual(etud)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/etud_bilan_ects/<int:etudid>")
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def etud_bilan_ects(etudid: int):
|
||||||
|
"""Page bilan de tous els ECTS acquis par un étudiant.
|
||||||
|
Plusieurs formations (eg DUT, LP) peuvent être concernées.
|
||||||
|
"""
|
||||||
|
etud = Identite.get_etud(etudid)
|
||||||
|
# Cherche les formations différentes (au sens des ECTS)
|
||||||
|
# suivies par l'étudiant: regroupe ses formsemestres
|
||||||
|
# diplome est la clé: en classique le code formation, en BUT le referentiel_competence_id
|
||||||
|
formsemestre_by_diplome = defaultdict(list)
|
||||||
|
for formsemestre in etud.get_formsemestres(recent_first=True):
|
||||||
|
diplome = (
|
||||||
|
formsemestre.formation.referentiel_competence.id
|
||||||
|
if (
|
||||||
|
formsemestre.formation.is_apc()
|
||||||
|
and formsemestre.formation.referentiel_competence
|
||||||
|
)
|
||||||
|
else formsemestre.formation.formation_code
|
||||||
|
)
|
||||||
|
formsemestre_by_diplome[diplome].append(formsemestre)
|
||||||
|
|
||||||
|
# Pour chaque liste de formsemestres d'un même "diplôme"
|
||||||
|
# liste les UE validées avec leurs ECTS
|
||||||
|
ects_by_diplome = {}
|
||||||
|
titre_by_diplome = {} # { diplome : titre }
|
||||||
|
validations_by_diplome = {} # { diplome : query validations UEs }
|
||||||
|
for diplome, formsemestres in formsemestre_by_diplome.items():
|
||||||
|
formsemestre = formsemestres[0]
|
||||||
|
titre_by_diplome[diplome] = formsemestre.formation.get_titre_version()
|
||||||
|
if formsemestre.formation.is_apc():
|
||||||
|
validations = cursus_but.but_validations_ues(etud, diplome)
|
||||||
|
else:
|
||||||
|
validations = ScolarFormSemestreValidation.validations_ues(
|
||||||
|
etud, formsemestre.formation.formation_code
|
||||||
|
)
|
||||||
|
validations_by_diplome[diplome] = [
|
||||||
|
validation
|
||||||
|
for validation in validations
|
||||||
|
if validation.code in CODES_UE_VALIDES
|
||||||
|
]
|
||||||
|
ects_by_diplome[diplome] = sum(
|
||||||
|
(validation.ue.ects or 0.0)
|
||||||
|
for validation in validations_by_diplome[diplome]
|
||||||
|
)
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"jury/etud_bilan_ects.j2",
|
||||||
|
etud=etud,
|
||||||
|
ects_by_diplome=ects_by_diplome,
|
||||||
|
formsemestre_by_diplome=formsemestre_by_diplome,
|
||||||
|
titre_by_diplome=titre_by_diplome,
|
||||||
|
validations_by_diplome=validations_by_diplome,
|
||||||
|
)
|
||||||
|
@ -56,9 +56,9 @@ cli.register(app)
|
|||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def inject_sco_utils():
|
def inject_sco_utils():
|
||||||
"Make scu and sco available in all Jinja templates"
|
"Make Permission, sco and scu available in all Jinja templates"
|
||||||
# if modified, put the same in conftest.py#27
|
# if modified, put the same in conftest.py#27
|
||||||
return {"scu": scu, "sco": ScoData()}
|
return {"Permission": Permission, "scu": scu, "sco": ScoData()}
|
||||||
|
|
||||||
|
|
||||||
@app.shell_context_processor
|
@app.shell_context_processor
|
||||||
|
@ -11,6 +11,7 @@ from app import models
|
|||||||
from app.auth.models import User, Role
|
from app.auth.models import User, Role
|
||||||
from app.auth.models import get_super_admin
|
from app.auth.models import get_super_admin
|
||||||
from app.scodoc import notesdb as ndb
|
from app.scodoc import notesdb as ndb
|
||||||
|
from app.scodoc.sco_permissions import Permission
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.views import ScoData
|
from app.views import ScoData
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ def test_client():
|
|||||||
@apptest.context_processor
|
@apptest.context_processor
|
||||||
def inject_sco_utils():
|
def inject_sco_utils():
|
||||||
"Make scu available in all Jinja templates"
|
"Make scu available in all Jinja templates"
|
||||||
return {"scu": scu, "sco": ScoData()}
|
return {"Permission": Permission, "scu": scu, "sco": ScoData()}
|
||||||
|
|
||||||
with apptest.test_request_context():
|
with apptest.test_request_context():
|
||||||
# initialize scodoc "g":
|
# initialize scodoc "g":
|
||||||
|
Loading…
Reference in New Issue
Block a user