forked from ScoDoc/ScoDoc
845 lines
30 KiB
Python
845 lines
30 KiB
Python
# -*- mode: python -*-
|
|
# -*- coding: utf-8 -*-
|
|
|
|
##############################################################################
|
|
#
|
|
# Gestion scolarite IUT
|
|
#
|
|
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
|
#
|
|
##############################################################################
|
|
|
|
"""ScoDoc fiche_etud
|
|
|
|
Fiche description d'un étudiant et de son parcours
|
|
|
|
"""
|
|
from flask import url_for, g, render_template, request
|
|
from flask_login import current_user
|
|
import sqlalchemy as sa
|
|
|
|
from app import log
|
|
from app.auth.models import User
|
|
from app.but import cursus_but, validations_view
|
|
from app.models import Adresse, EtudAnnotation, FormSemestre, Identite, ScoDocSiteConfig
|
|
from app.scodoc import (
|
|
codes_cursus,
|
|
html_sco_header,
|
|
htmlutils,
|
|
sco_archives_etud,
|
|
sco_bac,
|
|
sco_cursus,
|
|
sco_etud,
|
|
sco_groups,
|
|
sco_permissions_check,
|
|
sco_report,
|
|
)
|
|
from app.scodoc.html_sidebar import retreive_formsemestre_from_request
|
|
from app.scodoc.sco_bulletins import etud_descr_situation_semestre
|
|
from app.scodoc.sco_exceptions import ScoValueError
|
|
from app.scodoc.sco_formsemestre_validation import formsemestre_recap_parcours_table
|
|
from app.scodoc.sco_permissions import Permission
|
|
import app.scodoc.sco_utils as scu
|
|
|
|
|
|
def _menu_scolarite(
|
|
authuser, formsemestre: FormSemestre, etudid: int, etat_inscription: str
|
|
):
|
|
"""HTML pour menu "scolarite" pour un etudiant dans un semestre.
|
|
Le contenu du menu depend des droits de l'utilisateur et de l'état de l'étudiant.
|
|
"""
|
|
locked = not formsemestre.etat
|
|
if locked:
|
|
lockicon = scu.icontag("lock32_img", title="verrouillé", border="0")
|
|
return lockicon # no menu
|
|
if not authuser.has_permission(
|
|
Permission.EtudInscrit
|
|
) and not authuser.has_permission(Permission.EtudChangeGroups):
|
|
return "" # no menu
|
|
|
|
args = {"etudid": etudid, "formsemestre_id": formsemestre.id}
|
|
|
|
if etat_inscription != scu.DEMISSION:
|
|
dem_title = "Démission"
|
|
dem_url = "scolar.form_dem"
|
|
else:
|
|
dem_title = "Annuler la démission"
|
|
dem_url = "scolar.do_cancel_dem"
|
|
|
|
# Note: seul un etudiant inscrit (I) peut devenir défaillant.
|
|
if etat_inscription != codes_cursus.DEF:
|
|
def_title = "Déclarer défaillance"
|
|
def_url = "scolar.form_def"
|
|
elif etat_inscription == codes_cursus.DEF:
|
|
def_title = "Annuler la défaillance"
|
|
def_url = "scolar.do_cancel_def"
|
|
def_enabled = (
|
|
(etat_inscription != scu.DEMISSION)
|
|
and authuser.has_permission(Permission.EtudInscrit)
|
|
and not locked
|
|
)
|
|
items = [
|
|
{
|
|
"title": dem_title,
|
|
"endpoint": dem_url,
|
|
"args": args,
|
|
"enabled": authuser.has_permission(Permission.EtudInscrit) and not locked,
|
|
},
|
|
{
|
|
"title": "Validation du semestre (jury)",
|
|
"endpoint": "notes.formsemestre_validation_etud_form",
|
|
"args": args,
|
|
"enabled": authuser.has_permission(Permission.EtudInscrit) and not locked,
|
|
},
|
|
{
|
|
"title": def_title,
|
|
"endpoint": def_url,
|
|
"args": args,
|
|
"enabled": def_enabled,
|
|
},
|
|
{
|
|
"title": "Inscrire à un module optionnel (ou au sport)",
|
|
"endpoint": "notes.formsemestre_inscription_option",
|
|
"args": args,
|
|
"enabled": authuser.has_permission(Permission.EtudInscrit) and not locked,
|
|
},
|
|
{
|
|
"title": "Désinscrire (en cas d'erreur)",
|
|
"endpoint": "notes.formsemestre_desinscription",
|
|
"args": args,
|
|
"enabled": authuser.has_permission(Permission.EtudInscrit) and not locked,
|
|
},
|
|
{
|
|
"title": "Gérer les validations d'UEs antérieures",
|
|
"endpoint": "notes.formsemestre_validate_previous_ue",
|
|
"args": args,
|
|
"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",
|
|
"endpoint": "notes.formsemestre_ext_create_form",
|
|
"args": args,
|
|
"enabled": authuser.has_permission(Permission.EditFormSemestre),
|
|
},
|
|
{
|
|
"title": "Affecter les notes manquantes",
|
|
"endpoint": "notes.formsemestre_note_etuds_sans_notes",
|
|
"args": args,
|
|
"enabled": authuser.has_permission(Permission.EditAllNotes),
|
|
},
|
|
]
|
|
|
|
return htmlutils.make_menu(
|
|
"Scolarité", items, css_class="direction_etud", alone=True
|
|
)
|
|
|
|
|
|
def fiche_etud(etudid=None):
|
|
"fiche d'informations sur un etudiant"
|
|
restrict_etud_data = not current_user.has_permission(Permission.ViewEtudData)
|
|
try:
|
|
etud = Identite.get_etud(etudid)
|
|
except Exception as exc:
|
|
log(f"fiche_etud: etudid={etudid!r} request.args={request.args!r}")
|
|
raise ScoValueError("Étudiant inexistant !") from exc
|
|
# la sidebar est differente s'il y a ou pas un etudid
|
|
# voir html_sidebar.sidebar()
|
|
g.etudid = etudid
|
|
info = etud.to_dict_scodoc7(restrict=restrict_etud_data)
|
|
if etud.prenom_etat_civil:
|
|
info["etat_civil"] = (
|
|
"<h3>Etat-civil: "
|
|
+ etud.civilite_etat_civil_str
|
|
+ " "
|
|
+ etud.prenom_etat_civil
|
|
+ " "
|
|
+ etud.nom
|
|
+ "</h3>"
|
|
)
|
|
else:
|
|
info["etat_civil"] = ""
|
|
info["ScoURL"] = url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)
|
|
info["authuser"] = current_user
|
|
if restrict_etud_data:
|
|
info["info_naissance"] = ""
|
|
adresse = None
|
|
else:
|
|
info["info_naissance"] = info["date_naissance"]
|
|
if info["lieu_naissance"]:
|
|
info["info_naissance"] += " à " + info["lieu_naissance"]
|
|
if info["dept_naissance"]:
|
|
info["info_naissance"] += f" ({info['dept_naissance']})"
|
|
adresse = etud.adresses.first()
|
|
info.update(_format_adresse(adresse))
|
|
|
|
info.update(etud.inscription_descr())
|
|
info["etudfoto"] = etud.photo_html()
|
|
|
|
# Champ dépendant des permissions:
|
|
if current_user.has_permission(
|
|
Permission.EtudChangeAdr
|
|
) and current_user.has_permission(Permission.ViewEtudData):
|
|
info[
|
|
"modifadresse"
|
|
] = f"""<a class="stdlink" href="{
|
|
url_for("scolar.form_change_coordonnees",
|
|
scodoc_dept=g.scodoc_dept, etudid=etudid)
|
|
}">modifier adresse</a>"""
|
|
else:
|
|
info["modifadresse"] = ""
|
|
|
|
# Groupes:
|
|
inscription_courante = etud.inscription_courante()
|
|
sco_groups.etud_add_group_infos(
|
|
info,
|
|
inscription_courante.formsemestre.id if inscription_courante else None,
|
|
only_to_show=True,
|
|
)
|
|
# Parcours de l'étudiant
|
|
last_formsemestre = None
|
|
inscriptions = etud.inscriptions()
|
|
info["last_formsemestre_id"] = (
|
|
inscriptions[0].formsemestre.id if inscriptions else ""
|
|
)
|
|
|
|
sem_info = {}
|
|
for inscription in inscriptions:
|
|
formsemestre = inscription.formsemestre
|
|
if inscription.etat != scu.INSCRIT:
|
|
descr, _ = etud_descr_situation_semestre(
|
|
etudid,
|
|
formsemestre,
|
|
etud.e,
|
|
show_date_inscr=False,
|
|
)
|
|
grlink = f"""<span class="fontred">{descr["situation"]}</span>"""
|
|
else:
|
|
e = {"etudid": etudid}
|
|
sco_groups.etud_add_group_infos(e, formsemestre.id, only_to_show=True)
|
|
|
|
grlinks = []
|
|
for partition in e["partitions"].values():
|
|
if partition["partition_name"]:
|
|
gr_name = partition["group_name"]
|
|
else:
|
|
gr_name = "tous"
|
|
|
|
grlinks.append(
|
|
f"""<a class="discretelink" href="{
|
|
url_for('scolar.groups_view',
|
|
scodoc_dept=g.scodoc_dept, group_ids=partition['group_id'])
|
|
}" title="Liste du groupe {gr_name}">{gr_name}</a>
|
|
"""
|
|
)
|
|
grlink = ", ".join(grlinks)
|
|
# infos ajoutées au semestre dans le parcours (groupe, menu)
|
|
menu = _menu_scolarite(current_user, formsemestre, etudid, inscription.etat)
|
|
if menu:
|
|
sem_info[formsemestre.id] = (
|
|
"<table><tr><td>" + grlink + "</td><td>" + menu + "</td></tr></table>"
|
|
)
|
|
else:
|
|
sem_info[formsemestre.id] = grlink
|
|
|
|
if inscriptions:
|
|
Se = sco_cursus.get_situation_etud_cursus(etud, info["last_formsemestre_id"])
|
|
info["liste_inscriptions"] = formsemestre_recap_parcours_table(
|
|
Se,
|
|
etudid,
|
|
with_links=False,
|
|
sem_info=sem_info,
|
|
with_all_columns=False,
|
|
)
|
|
info["link_bul_pdf"] = (
|
|
"""<span class="link_bul_pdf fontred">PDF interdits par l'admin.</span>"""
|
|
if ScoDocSiteConfig.is_bul_pdf_disabled()
|
|
else f"""
|
|
<span class="link_bul_pdf">
|
|
<a class="stdlink" href="{
|
|
url_for("notes.etud_bulletins_pdf", scodoc_dept=g.scodoc_dept, etudid=etudid)
|
|
}">Tous les bulletins</a>
|
|
</span>
|
|
"""
|
|
)
|
|
last_formsemestre: FormSemestre = inscriptions[0].formsemestre
|
|
if last_formsemestre.formation.is_apc() and last_formsemestre.semestre_id > 2:
|
|
info[
|
|
"link_bul_pdf"
|
|
] += f"""
|
|
<span class="link_bul_pdf">
|
|
<a class="stdlink" href="{
|
|
url_for("notes.validation_rcues",
|
|
scodoc_dept=g.scodoc_dept, etudid=etudid, formsemestre_id=last_formsemestre.id)
|
|
}">Visualiser les compétences BUT</a>
|
|
</span>
|
|
"""
|
|
if current_user.has_permission(Permission.EtudInscrit):
|
|
info[
|
|
"link_inscrire_ailleurs"
|
|
] = f"""<span class="link_bul_pdf"><a class="stdlink" href="{
|
|
url_for("notes.formsemestre_inscription_with_modules_form",
|
|
scodoc_dept=g.scodoc_dept, etudid=etudid)
|
|
}">Inscrire à un autre semestre</a></span>
|
|
<span class="link_bul_pdf"><a class="stdlink" href="{
|
|
url_for("notes.jury_delete_manual",
|
|
scodoc_dept=g.scodoc_dept, etudid=etudid)
|
|
}">Éditer toutes décisions de jury</a></span>
|
|
"""
|
|
|
|
else:
|
|
info["link_inscrire_ailleurs"] = ""
|
|
else:
|
|
# non inscrit
|
|
l = [f"""<p><b>Étudiant{etud.e} non inscrit{etud.e}"""]
|
|
if current_user.has_permission(Permission.EtudInscrit):
|
|
l.append(
|
|
f"""<a href="{
|
|
url_for("notes.formsemestre_inscription_with_modules_form",
|
|
scodoc_dept=g.scodoc_dept, etudid=etudid)
|
|
}">inscrire</a></li>"""
|
|
)
|
|
l.append("</b></b>")
|
|
info["liste_inscriptions"] = "\n".join(l)
|
|
info["link_bul_pdf"] = ""
|
|
info["link_inscrire_ailleurs"] = ""
|
|
|
|
# Liste des annotations
|
|
html_annotations_list = "\n".join(
|
|
[] if restrict_etud_data else get_html_annotations_list(etud)
|
|
)
|
|
|
|
# fiche admission
|
|
if etud.admission:
|
|
infos_admission = _infos_admission(etud, restrict_etud_data)
|
|
has_adm_notes = any(
|
|
infos_admission[k] for k in ("math", "physique", "anglais", "francais")
|
|
)
|
|
has_bac_info = any(
|
|
infos_admission[k]
|
|
for k in (
|
|
"bac_specialite",
|
|
"annee_bac",
|
|
"rapporteur",
|
|
"commentaire",
|
|
"classement",
|
|
"type_admission",
|
|
"rap",
|
|
)
|
|
)
|
|
if has_bac_info or has_adm_notes:
|
|
adm_tmpl = """<!-- Donnees admission -->
|
|
<div class="fichetitre">Informations admission</div>
|
|
"""
|
|
if has_adm_notes:
|
|
adm_tmpl += """
|
|
<table>
|
|
<tr><th>Bac</th><th>Année</th><th>Rg</th>
|
|
<th>Math</th><th>Physique</th><th>Anglais</th><th>Français</th></tr>
|
|
<tr>
|
|
<td>%(bac_specialite)s</td>
|
|
<td>%(annee_bac)s </td>
|
|
<td>%(classement)s</td>
|
|
<td>%(math)s</td><td>%(physique)s</td><td>%(anglais)s</td><td>%(francais)s</td>
|
|
</tr>
|
|
</table>
|
|
"""
|
|
adm_tmpl += """
|
|
<div>Bac %(bac_specialite)s obtenu en %(annee_bac)s </div>
|
|
<div class="info_lycee">%(info_lycee)s</div>"""
|
|
if infos_admission["type_admission"] or infos_admission["classement"]:
|
|
adm_tmpl += """<div class="vadmission">"""
|
|
if infos_admission["type_admission"]:
|
|
adm_tmpl += """<span>Voie d'admission: <span class="etud_type_admission">%(type_admission)s</span></span> """
|
|
if infos_admission["classement"]:
|
|
adm_tmpl += """<span>Rang admission: <span class="etud_type_admission">%(classement)s</span></span>"""
|
|
if infos_admission["type_admission"] or infos_admission["classement"]:
|
|
adm_tmpl += "</div>"
|
|
if infos_admission["rap"]:
|
|
adm_tmpl += """<div class="note_rapporteur">%(rap)s</div>"""
|
|
adm_tmpl += """</div>"""
|
|
else:
|
|
adm_tmpl = "" # pas de boite "info admission"
|
|
info["adm_data"] = adm_tmpl % infos_admission
|
|
else:
|
|
info["adm_data"] = ""
|
|
|
|
# Fichiers archivés:
|
|
info["fichiers_archive_htm"] = (
|
|
""
|
|
if restrict_etud_data
|
|
else (
|
|
'<div class="fichetitre">Fichiers associés</div>'
|
|
+ sco_archives_etud.etud_list_archives_html(etud)
|
|
)
|
|
)
|
|
|
|
# Devenir de l'étudiant:
|
|
has_debouche = True
|
|
if sco_permissions_check.can_edit_suivi():
|
|
suivi_readonly = "0"
|
|
link_add_suivi = """<li class="adddebouche">
|
|
<a id="adddebouchelink" class="stdlink" href="#">ajouter une ligne</a>
|
|
</li>"""
|
|
else:
|
|
suivi_readonly = "1"
|
|
link_add_suivi = ""
|
|
if has_debouche:
|
|
info[
|
|
"debouche_html"
|
|
] = f"""<div id="fichedebouche"
|
|
data-readonly="{suivi_readonly}"
|
|
data-etudid="{info['etudid']}">
|
|
<span class="debouche_tit">Devenir:</span>
|
|
<div><form>
|
|
<ul class="listdebouches">
|
|
{link_add_suivi}
|
|
</ul>
|
|
</form></div>
|
|
</div>"""
|
|
else:
|
|
info["debouche_html"] = "" # pas de boite "devenir"
|
|
|
|
# Inscriptions
|
|
info[
|
|
"inscriptions_mkup"
|
|
] = f"""<div class="ficheinscriptions" id="ficheinscriptions">
|
|
<div class="fichetitre">Cursus</div>{info["liste_inscriptions"]}
|
|
{info["link_bul_pdf"]} {info["link_inscrire_ailleurs"]}
|
|
</div>"""
|
|
|
|
#
|
|
if info["groupes"].strip():
|
|
info[
|
|
"groupes_row"
|
|
] = f"""<tr>
|
|
<td class="fichetitre2">Groupes :</td><td>{info['groupes']}</td>
|
|
</tr>"""
|
|
else:
|
|
info["groupes_row"] = ""
|
|
info["menus_etud"] = menus_etud(etudid)
|
|
if info["boursier"] and not restrict_etud_data:
|
|
info["bourse_span"] = """<span class="boursier">boursier</span>"""
|
|
else:
|
|
info["bourse_span"] = ""
|
|
|
|
# Liens vers compétences BUT
|
|
if last_formsemestre and last_formsemestre.formation.is_apc():
|
|
but_cursus = cursus_but.EtudCursusBUT(etud, last_formsemestre.formation)
|
|
refcomp = last_formsemestre.formation.referentiel_competence
|
|
if refcomp:
|
|
ue_validation_by_niveau = validations_view.get_ue_validation_by_niveau(
|
|
refcomp, etud
|
|
)
|
|
ects_total = sum((v.ects() for v in ue_validation_by_niveau.values()))
|
|
else:
|
|
ects_total = ""
|
|
info[
|
|
"but_cursus_mkup"
|
|
] = f"""
|
|
<div class="section_but">
|
|
{render_template(
|
|
"but/cursus_etud.j2",
|
|
cursus=but_cursus,
|
|
scu=scu,
|
|
)}
|
|
<div class="fiche_but_col2">
|
|
<div class="link_validation_rcues">
|
|
<a class="stdlink" href="{url_for("notes.validation_rcues",
|
|
scodoc_dept=g.scodoc_dept, etudid=etudid,
|
|
formsemestre_id=last_formsemestre.id)}"
|
|
title="Visualiser les compétences BUT"
|
|
>
|
|
<img src="/ScoDoc/static/icons/parcours-but.png" alt="validation_rcues" height="100px"/>
|
|
<div style="text-align: center;">Compétences BUT</div>
|
|
</a>
|
|
</div>
|
|
<div class="fiche_total_etcs">
|
|
Total ECTS BUT: {ects_total:g}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
"""
|
|
else:
|
|
info["but_cursus_mkup"] = ""
|
|
|
|
adresse_template = (
|
|
""
|
|
if restrict_etud_data
|
|
else """
|
|
<!-- Adresse -->
|
|
<div class="ficheadresse" id="ficheadresse">
|
|
<table>
|
|
<tr>
|
|
<td class="fichetitre2">Adresse :</td>
|
|
<td> %(domicile)s %(codepostaldomicile)s %(villedomicile)s %(paysdomicile)s
|
|
%(modifadresse)s
|
|
%(telephones)s
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
"""
|
|
)
|
|
|
|
info_naissance = (
|
|
f"""<tr><td class="fichetitre2">Né{etud.e} le :</td>
|
|
<td>{info["info_naissance"]}</td></tr>
|
|
"""
|
|
if info["info_naissance"]
|
|
else ""
|
|
)
|
|
situation_template = (
|
|
f"""
|
|
<div class="fichesituation">
|
|
<div class="fichetablesitu">
|
|
<table>
|
|
<tr><td class="fichetitre2">Situation :</td><td>%(situation)s %(bourse_span)s</td></tr>
|
|
%(groupes_row)s
|
|
{info_naissance}
|
|
</table>
|
|
"""
|
|
+ adresse_template
|
|
+ """
|
|
</div>
|
|
</div>
|
|
"""
|
|
)
|
|
|
|
info["annotations_mkup"] = (
|
|
f"""
|
|
<div class="ficheannotations">
|
|
<div class="fichetitre">Annotations</div>
|
|
<table id="etudannotations">{html_annotations_list}</table>
|
|
|
|
<form action="doAddAnnotation" method="GET" class="noprint">
|
|
<input type="hidden" name="etudid" value="{etudid}">
|
|
<b>Ajouter une annotation sur {etud.nomprenom}: </b>
|
|
<div>
|
|
<textarea name="comment" rows="4" cols="50" value=""></textarea>
|
|
<div style="font-size: small; font-style: italic;">
|
|
<div>Ces annotations sont lisibles par tous les utilisateurs ayant la permission
|
|
<tt>ViewEtudData</tt> dans ce département (souvent les enseignants et le
|
|
secrétariat).
|
|
</div>
|
|
<div>L'annotation commençant par "PE:" est un avis de poursuite d'études.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<input type="hidden" name="author" width=12 value="{current_user}">
|
|
<input type="submit" value="Ajouter annotation">
|
|
</form>
|
|
</div>
|
|
"""
|
|
if not restrict_etud_data
|
|
else ""
|
|
)
|
|
|
|
tmpl = (
|
|
"""<div class="menus_etud">%(menus_etud)s</div>
|
|
<div class="fiche_etud" id="fiche_etud"><table>
|
|
<tr><td>
|
|
<h2>%(nomprenom)s (%(inscription)s)</h2>
|
|
%(etat_civil)s
|
|
<span>%(email_link)s</span>
|
|
</td><td class="photocell">
|
|
<a href="etud_photo_orig_page/%(etudid)s">%(etudfoto)s</a>
|
|
</td></tr></table>
|
|
"""
|
|
+ situation_template
|
|
+ """
|
|
|
|
%(inscriptions_mkup)s
|
|
|
|
%(but_cursus_mkup)s
|
|
|
|
<div class="ficheadmission">
|
|
%(adm_data)s
|
|
|
|
%(fichiers_archive_htm)s
|
|
</div>
|
|
|
|
%(debouche_html)s
|
|
|
|
%(annotations_mkup)s
|
|
|
|
<div class="code_nip">code NIP: %(code_nip)s</div>
|
|
|
|
</div>
|
|
"""
|
|
)
|
|
header = html_sco_header.sco_header(
|
|
page_title=f"Fiche étudiant {etud.nomprenom}",
|
|
cssstyles=[
|
|
"libjs/jQuery-tagEditor/jquery.tag-editor.css",
|
|
"css/jury_but.css",
|
|
"css/cursus_but.css",
|
|
],
|
|
javascripts=[
|
|
"libjs/jinplace-1.2.1.min.js",
|
|
"js/ue_list.js",
|
|
"libjs/jQuery-tagEditor/jquery.tag-editor.min.js",
|
|
"libjs/jQuery-tagEditor/jquery.caret.min.js",
|
|
"js/recap_parcours.js",
|
|
"js/etud_debouche.js",
|
|
],
|
|
)
|
|
return header + tmpl % info + html_sco_header.sco_footer()
|
|
|
|
|
|
def _format_adresse(adresse: Adresse | None) -> dict:
|
|
"""{ "telephonestr" : ..., "telephonemobilestr" : ... } (formats html)"""
|
|
d = {
|
|
"telephonestr": (
|
|
("<b>Tél.:</b> " + scu.format_telephone(adresse.telephone))
|
|
if (adresse and adresse.telephone)
|
|
else ""
|
|
),
|
|
"telephonemobilestr": (
|
|
("<b>Mobile:</b> " + scu.format_telephone(adresse.telephonemobile))
|
|
if (adresse and adresse.telephonemobile)
|
|
else ""
|
|
),
|
|
# e-mail:
|
|
"email_link": (
|
|
", ".join(
|
|
[
|
|
f"""<a class="stdlink" href="mailto:{m}">{m}</a>"""
|
|
for m in [adresse.email, adresse.emailperso]
|
|
if m
|
|
]
|
|
)
|
|
if adresse and (adresse.email or adresse.emailperso)
|
|
else ""
|
|
),
|
|
"domicile": (
|
|
(adresse.domicile or "")
|
|
if adresse
|
|
and (
|
|
adresse.domicile or adresse.codepostaldomicile or adresse.villedomicile
|
|
)
|
|
else "<em>inconnue</em>"
|
|
),
|
|
"paysdomicile": (
|
|
f"{sco_etud.format_pays(adresse.paysdomicile)}"
|
|
if adresse and adresse.paysdomicile
|
|
else ""
|
|
),
|
|
}
|
|
d["telephones"] = (
|
|
f"<br>{d['telephonestr']} {d['telephonemobilestr']}"
|
|
if adresse and (adresse.telephone or adresse.telephonemobile)
|
|
else ""
|
|
)
|
|
return d
|
|
|
|
|
|
def _infos_admission(etud: Identite, restrict_etud_data: bool) -> dict:
|
|
"""dict with admission data, restricted or not"""
|
|
# info sur rapporteur et son commentaire
|
|
rap = ""
|
|
if not restrict_etud_data:
|
|
if etud.admission.rapporteur or etud.admission.commentaire:
|
|
rap = "Note du rapporteur"
|
|
if etud.admission.rapporteur:
|
|
rap += f" ({etud.admission.rapporteur})"
|
|
rap += ": "
|
|
if etud.admission.commentaire:
|
|
rap += f"<em>{etud.admission.commentaire}</em>"
|
|
# nom du lycée
|
|
if restrict_etud_data:
|
|
info_lycee = ""
|
|
elif etud.admission.nomlycee:
|
|
info_lycee = "Lycée " + sco_etud.format_lycee(etud.admission.nomlycee)
|
|
if etud.admission.villelycee:
|
|
info_lycee += f" ({etud.admission.villelycee})"
|
|
info_lycee += "<br>"
|
|
elif etud.admission.codelycee:
|
|
info_lycee = sco_etud.format_lycee_from_code(etud.admission.codelycee)
|
|
else:
|
|
info_lycee = ""
|
|
|
|
return {
|
|
# infos accessibles à tous:
|
|
"bac_specialite": f"{etud.admission.bac or ''}{(' '+(etud.admission.specialite or '')) if etud.admission.specialite else ''}",
|
|
"annee_bac": etud.admission.annee_bac or "",
|
|
# infos protégées par ViewEtudData:
|
|
"info_lycee": info_lycee,
|
|
"rapporteur": etud.admission.rapporteur if not restrict_etud_data else "",
|
|
"rap": rap,
|
|
"commentaire": (
|
|
(etud.admission.commentaire or "") if not restrict_etud_data else ""
|
|
),
|
|
"classement": (
|
|
(etud.admission.classement or "") if not restrict_etud_data else ""
|
|
),
|
|
"type_admission": (
|
|
(etud.admission.type_admission or "") if not restrict_etud_data else ""
|
|
),
|
|
"math": (etud.admission.math or "") if not restrict_etud_data else "",
|
|
"physique": (etud.admission.physique or "") if not restrict_etud_data else "",
|
|
"anglais": (etud.admission.anglais or "") if not restrict_etud_data else "",
|
|
"francais": (etud.admission.francais or "") if not restrict_etud_data else "",
|
|
}
|
|
|
|
|
|
def get_html_annotations_list(etud: Identite) -> list[str]:
|
|
"""Liste de chaînes html décrivant les annotations."""
|
|
html_annotations_list = []
|
|
annotations = EtudAnnotation.query.filter_by(etudid=etud.id).order_by(
|
|
sa.desc(EtudAnnotation.date)
|
|
)
|
|
for annot in annotations:
|
|
del_link = (
|
|
f"""<td class="annodel"><a href="{
|
|
url_for("scolar.doSuppressAnnotation",
|
|
scodoc_dept=g.scodoc_dept, etudid=etud.id, annotation_id=annot.id)}">{
|
|
scu.icontag(
|
|
"delete_img",
|
|
border="0",
|
|
alt="suppress",
|
|
title="Supprimer cette annotation",
|
|
)
|
|
}</a></td>"""
|
|
if sco_permissions_check.can_suppress_annotation(annot.id)
|
|
else ""
|
|
)
|
|
|
|
author = User.query.filter_by(user_name=annot.author).first()
|
|
html_annotations_list.append(
|
|
f"""<tr><td><span class="annodate">Le {
|
|
annot.date.strftime(scu.DATE_FMT) if annot.date else "?"}
|
|
par {author.get_prenomnom() if author else "?"} :
|
|
</span><span class="annoc">{annot.comment or ""}</span></td>{del_link}</tr>
|
|
"""
|
|
)
|
|
return html_annotations_list
|
|
|
|
|
|
def menus_etud(etudid):
|
|
"""Menu etudiant (operations sur l'etudiant)"""
|
|
authuser = current_user
|
|
|
|
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
|
|
|
menuEtud = [
|
|
{
|
|
"title": etud["nomprenom"],
|
|
"endpoint": "scolar.fiche_etud",
|
|
"args": {"etudid": etud["etudid"]},
|
|
"enabled": True,
|
|
"helpmsg": "Fiche étudiant",
|
|
},
|
|
{
|
|
"title": "Changer la photo",
|
|
"endpoint": "scolar.form_change_photo",
|
|
"args": {"etudid": etud["etudid"]},
|
|
"enabled": authuser.has_permission(Permission.EtudChangeAdr),
|
|
},
|
|
{
|
|
"title": "Changer les données identité/admission",
|
|
"endpoint": "scolar.etudident_edit_form",
|
|
"args": {"etudid": etud["etudid"]},
|
|
"enabled": authuser.has_permission(Permission.EtudInscrit)
|
|
and authuser.has_permission(Permission.ViewEtudData),
|
|
},
|
|
{
|
|
"title": "Copier dans un autre département...",
|
|
"endpoint": "scolar.etud_copy_in_other_dept",
|
|
"args": {"etudid": etud["etudid"]},
|
|
"enabled": authuser.has_permission(Permission.EtudInscrit),
|
|
},
|
|
{
|
|
"title": "Supprimer cet étudiant...",
|
|
"endpoint": "scolar.etudident_delete",
|
|
"args": {"etudid": etud["etudid"]},
|
|
"enabled": authuser.has_permission(Permission.EtudInscrit),
|
|
},
|
|
{
|
|
"title": "Voir le journal...",
|
|
"endpoint": "scolar.showEtudLog",
|
|
"args": {"etudid": etud["etudid"]},
|
|
"enabled": True,
|
|
},
|
|
]
|
|
|
|
return htmlutils.make_menu(
|
|
"Étudiant", menuEtud, alone=True, css_class="menu-etudiant"
|
|
)
|
|
|
|
|
|
def etud_info_html(etudid, with_photo="1", debug=False):
|
|
"""An HTML div with basic information and links about this etud.
|
|
Used for popups information windows.
|
|
"""
|
|
formsemestre_id = retreive_formsemestre_from_request()
|
|
with_photo = int(with_photo)
|
|
etud = Identite.get_etud(etudid)
|
|
|
|
photo_html = etud.photo_html(title="fiche de " + etud.nomprenom)
|
|
code_cursus, _ = sco_report.get_code_cursus_etud(
|
|
etud, formsemestres=etud.get_formsemestres(), prefix="S", separator=", "
|
|
)
|
|
if etud.admission:
|
|
bac = sco_bac.Baccalaureat(etud.admission.bac, etud.admission.specialite)
|
|
bac_abbrev = bac.abbrev()
|
|
else:
|
|
bac_abbrev = "-"
|
|
H = f"""<div class="etud_info_div">
|
|
<div class="eid_left">
|
|
<div class="eid_nom"><div><a class="stdlink" target="_blank" href="{
|
|
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
|
|
}">{etud.nomprenom}</a></div></div>
|
|
<div class="eid_info eid_bac">Bac: <span class="eid_bac">{bac_abbrev}</span></div>
|
|
<div class="eid_info eid_parcours">{code_cursus}</div>
|
|
"""
|
|
|
|
# Informations sur l'etudiant dans le semestre courant:
|
|
if formsemestre_id: # un semestre est spécifié par la page
|
|
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
|
else:
|
|
# le semestre "en cours" pour l'étudiant
|
|
inscription_courante = etud.inscription_courante()
|
|
formsemestre = (
|
|
inscription_courante.formsemestre if inscription_courante else None
|
|
)
|
|
|
|
if formsemestre:
|
|
groups = sco_groups.get_etud_groups(etudid, formsemestre.id)
|
|
grc = sco_groups.listgroups_abbrev(groups)
|
|
H += f"""<div class="eid_info">En <b>S{formsemestre.semestre_id}</b>: {grc}</div>"""
|
|
H += "</div>" # fin partie gauche (eid_left)
|
|
if with_photo:
|
|
H += '<span class="eid_right">' + photo_html + "</span>"
|
|
|
|
H += "</div>"
|
|
if debug:
|
|
return (
|
|
html_sco_header.standard_html_header()
|
|
+ H
|
|
+ html_sco_header.standard_html_footer()
|
|
)
|
|
else:
|
|
return H
|