# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2021 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 ficheEtud Fiche description d'un étudiant et de son parcours """ import sco_utils as scu import notesdb as ndb from notes_log import log import scolars import sco_bac import sco_photos import sco_groups import sco_formsemestre from scolars import format_telephone, format_pays, make_etud_args import sco_formsemestre_status import htmlutils import html_sco_header from sco_bulletins import etud_descr_situation_semestre import sco_parcours_dut import sco_codes_parcours from sco_formsemestre_validation import formsemestre_recap_parcours_table import sco_archives_etud import sco_report from sco_permissions import ( ScoEtudChangeGroups, ScoEtudInscrit, ScoImplement, ScoEtudChangeAdr, ) from sco_exceptions import ScoValueError def _menuScolarite(context, authuser, sem, etudid): """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 = sem["etat"] != "1" if locked: lockicon = scu.icontag("lock32_img", title="verrouillé", border="0") return lockicon # no menu if not authuser.has_permission( ScoEtudInscrit, context ) and not authuser.has_permission(Permission.ScoEtudChangeGroups, context): return "" # no menu ins = sem["ins"] args = {"etudid": etudid, "formsemestre_id": ins["formsemestre_id"]} if ins["etat"] != "D": dem_title = "Démission" dem_url = "formDem" else: dem_title = "Annuler la démission" dem_url = "doCancelDem" # Note: seul un etudiant inscrit (I) peut devenir défaillant. if ins["etat"] != sco_codes_parcours.DEF: def_title = "Déclarer défaillance" def_url = "formDef" elif ins["etat"] == sco_codes_parcours.DEF: def_title = "Annuler la défaillance" def_url = "doCancelDef" def_enabled = ( (ins["etat"] != "D") and authuser.has_permission(Permission.ScoEtudInscrit, context) and not locked ) items = [ { "title": dem_title, "endpoint": dem_url, "args": args, "enabled": authuser.has_permission(Permission.ScoEtudInscrit, context) and not locked, }, { "title": "Validation du semestre (jury)", "endpoint": "notes.formsemestre_validation_etud_form", "args": args, "enabled": authuser.has_permission(Permission.ScoEtudInscrit, context) and not locked, }, {"title": def_title, "endpoint": def_url, "enabled": def_enabled}, { "title": "Inscrire à un module optionnel (ou au sport)", "endpoint": "notes.formsemestre_inscription_option", "args": args, "enabled": authuser.has_permission(Permission.ScoEtudInscrit, context) and not locked, }, { "title": "Désinscrire (en cas d'erreur)", "endpoint": "notes.formsemestre_desinscription", "enabled": authuser.has_permission(Permission.ScoEtudInscrit, context) and not locked, }, { "title": "Inscrire à un autre semestre", "endpoint": "notes.formsemestre_inscription_with_modules_form", "args": {"etudid": etudid}, "enabled": authuser.has_permission(Permission.ScoEtudInscrit, context), }, { "title": "Enregistrer un semestre effectué ailleurs", "endpoint": "notes.formsemestre_ext_create_form", "enabled": authuser.has_permission(Permission.ScoImplement, context), }, ] return htmlutils.make_menu( "Scolarité", items, css_class="direction_etud", alone=True ) def ficheEtud(context, etudid=None, REQUEST=None): "fiche d'informations sur un etudiant" authuser = REQUEST.AUTHENTICATED_USER cnx = ndb.GetDBConnexion() if etudid and REQUEST: # la sidebar est differente s'il y a ou pas un etudid # voir html_sidebar.sidebar() REQUEST.form["etudid"] = etudid args = make_etud_args(etudid=etudid, REQUEST=REQUEST) etuds = scolars.etudident_list(cnx, args) if not etuds: log("ficheEtud: etudid=%s REQUEST.form=%s" % (etudid, REQUEST.form)) raise ScoValueError("Etudiant inexistant !") etud = etuds[0] etudid = etud["etudid"] scolars.fillEtudsInfo(context, [etud]) # info = etud info["ScoURL"] = scu.ScoURL() info["authuser"] = authuser info["info_naissance"] = info["date_naissance"] if info["lieu_naissance"]: info["info_naissance"] += " à " + info["lieu_naissance"] if info["dept_naissance"]: info["info_naissance"] += " (%s)" % info["dept_naissance"] info["etudfoto"] = sco_photos.etud_photo_html(context, etud, REQUEST=REQUEST) if ( (not info["domicile"]) and (not info["codepostaldomicile"]) and (not info["villedomicile"]) ): info["domicile"] = "inconnue" if info["paysdomicile"]: pays = format_pays(info["paysdomicile"]) if pays: info["paysdomicile"] = "(%s)" % pays else: info["paysdomicile"] = "" if info["telephone"] or info["telephonemobile"]: info["telephones"] = "
%s    %s" % ( info["telephonestr"], info["telephonemobilestr"], ) else: info["telephones"] = "" # e-mail: if info["email_default"]: info["emaillink"] = ", ".join( [ '%s' % (m, m) for m in [etud["email"], etud["emailperso"]] if m ] ) else: info["emaillink"] = "(pas d'adresse e-mail)" # champs dependant des permissions if authuser.has_permission(Permission.ScoEtudChangeAdr, context): info["modifadresse"] = ( 'modifier adresse' % etudid ) else: info["modifadresse"] = "" # Groupes: sco_groups.etud_add_group_infos(context, info, info["cursem"]) # Parcours de l'étudiant if info["sems"]: info["last_formsemestre_id"] = info["sems"][0]["formsemestre_id"] else: info["last_formsemestre_id"] = "" sem_info = {} for sem in info["sems"]: if sem["ins"]["etat"] != "I": descr, _ = etud_descr_situation_semestre( context.Notes, etudid, sem["formsemestre_id"], info["ne"], show_date_inscr=False, ) grlink = '%s' % descr["situation"] else: group = sco_groups.get_etud_main_group(context, etudid, sem) if group["partition_name"]: gr_name = group["group_name"] else: gr_name = "tous" grlink = ( 'groupe %s' % (group["group_id"], gr_name) ) # infos ajoutées au semestre dans le parcours (groupe, menu) menu = _menuScolarite(context, authuser, sem, etudid) if menu: sem_info[sem["formsemestre_id"]] = ( "
" + grlink + "" + menu + "
" ) else: sem_info[sem["formsemestre_id"]] = grlink if info["sems"]: Se = sco_parcours_dut.SituationEtudParcours( context.Notes, etud, info["last_formsemestre_id"] ) info["liste_inscriptions"] = formsemestre_recap_parcours_table( context.Notes, Se, etudid, with_links=False, sem_info=sem_info, with_all_columns=False, a_url="Notes/", ) info["link_bul_pdf"] = ( 'tous les bulletins' % etud ) else: # non inscrit l = ["

Etudiant%s non inscrit%s" % (info["ne"], info["ne"])] if authuser.has_permission(Permission.ScoEtudInscrit, context): l.append( 'inscrire' % (scu.ScoURL(), etudid) ) l.append("") info["liste_inscriptions"] = "\n".join(l) info["link_bul_pdf"] = "" # Liste des annotations alist = [] annos = scolars.etud_annotations_list(cnx, args={"etudid": etudid}) for a in annos: if not sco_permissions.can_suppress_annotation(context, a["id"], REQUEST): a["dellink"] = "" else: a[ "dellink" ] = '%s' % ( etudid, a["id"], scu.icontag( "delete_img", border="0", alt="suppress", title="Supprimer cette annotation", ), ) alist.append( 'Le %(date)s par %(zope_authenticated_user)s : %(comment)s%(dellink)s' % a ) info["liste_annotations"] = "\n".join(alist) # fiche admission has_adm_notes = ( info["math"] or info["physique"] or info["anglais"] or info["francais"] ) has_bac_info = ( info["bac"] or info["specialite"] or info["annee_bac"] or info["rapporteur"] or info["commentaire"] or info["classement"] or info["type_admission"] ) if has_bac_info or has_adm_notes: adm_tmpl = """

Informations admission
""" if has_adm_notes: adm_tmpl += """
BacAnnéeRg MathPhysiqueAnglaisFrançais
%(bac)s (%(specialite)s) %(annee_bac)s %(classement)s %(math)s%(physique)s%(anglais)s%(francais)s
""" adm_tmpl += """
Bac %(bac)s (%(specialite)s) obtenu en %(annee_bac)s
%(ilycee)s
""" if info["type_admission"] or info["classement"]: adm_tmpl += """
""" if info["type_admission"]: adm_tmpl += """Voie d'admission: %(type_admission)s """ if info["classement"]: adm_tmpl += """Rang admission: %(classement)s""" if info["type_admission"] or info["classement"]: adm_tmpl += "
" if info["rap"]: adm_tmpl += """
%(rap)s
""" adm_tmpl += """""" else: adm_tmpl = "" # pas de boite "info admission" info["adm_data"] = adm_tmpl % info # Fichiers archivés: info["fichiers_archive_htm"] = ( '
Fichiers associés
' + sco_archives_etud.etud_list_archives_html(context, REQUEST, etudid) ) # Devenir de l'étudiant: has_debouche = True # info['debouche'] if sco_permissions.can_edit_suivi(context, REQUEST): suivi_readonly = "0" link_add_suivi = """
  • ajouter une ligne
  • """ else: suivi_readonly = "1" link_add_suivi = "" if has_debouche: info[ "debouche_html" ] = """
    Devenir:
      %s
    """ % ( suivi_readonly, info["etudid"], link_add_suivi, ) else: info["debouche_html"] = "" # pas de boite "devenir" # if info["liste_annotations"]: info["tit_anno"] = '
    Annotations
    ' else: info["tit_anno"] = "" # Inscriptions if info["sems"]: # XXX rcl unused ? à voir rcl = ( """(récapitulatif parcours)""" % info ) else: rcl = "" info[ "inscriptions_mkup" ] = """
    Parcours
    %s %s
    """ % ( info["liste_inscriptions"], info["link_bul_pdf"], ) # if info["groupes"].strip(): info["groupes_row"] = ( 'Groupe :%(groupes)s' % info ) else: info["groupes_row"] = "" info["menus_etud"] = menus_etud(context, REQUEST) tmpl = """

    %(nomprenom)s (%(inscription)s)

    %(emaillink)s
    %(etudfoto)s
    %(groupes_row)s
    Situation :%(situation)s
    Né%(ne)s le :%(info_naissance)s
    Adresse : %(domicile)s %(codepostaldomicile)s %(villedomicile)s %(paysdomicile)s %(modifadresse)s %(telephones)s
    %(inscriptions_mkup)s
    %(adm_data)s %(fichiers_archive_htm)s
    %(debouche_html)s
    %(tit_anno)s %(liste_annotations)s
    Ajouter une annotation sur %(nomprenom)s:

    Ces annotations sont lisibles par tous les enseignants et le secrétariat.
    L'annotation commençant par "PE:" est un avis de poursuite d'études.
    code NIP: %(code_nip)s
    """ header = html_sco_header.sco_header( context, REQUEST, page_title="Fiche étudiant %(prenom)s %(nom)s" % info, cssstyles=["libjs/jQuery-tagEditor/jquery.tag-editor.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(context, REQUEST) def menus_etud(context, REQUEST=None): """Menu etudiant (operations sur l'etudiant)""" if not REQUEST.form.has_key("etudid"): return "" authuser = REQUEST.AUTHENTICATED_USER etud = scolars.get_etud_info(filled=1, REQUEST=REQUEST)[0] menuEtud = [ { "title": etud["nomprenom"], "endpoint": "scolar.ficheEtud", "args": {"etudid": etud["etudid"]}, "enabled": True, "helpmsg": "Fiche étudiant", }, { "title": "Changer la photo", "endpoint": "scolar.formChangePhoto", "args": {"etudid": etud["etudid"]}, "enabled": authuser.has_permission(Permission.ScoEtudChangeAdr, context), }, { "title": "Changer les données identité/admission", "endpoint": "scolar.etudident_edit_form", "args": {"etudid": etud["etudid"]}, "enabled": authuser.has_permission(Permission.ScoEtudInscrit, context), }, { "title": "Supprimer cet étudiant...", "endpoint": "scolar.etudident_delete", "args": {"etudid": etud["etudid"]}, "enabled": authuser.has_permission(Permission.ScoEtudInscrit, context), }, { "title": "Voir le journal...", "endpoint": "scolar.showEtudLog", "args": {"etudid": etud["etudid"]}, "enabled": True, }, ] return htmlutils.make_menu("Etudiant", menuEtud, alone=True) def etud_info_html(context, etudid, with_photo="1", REQUEST=None, debug=False): """An HTML div with basic information and links about this etud. Used for popups information windows. """ try: context = context.Notes except: pass # log('etud_info_html: %s' % REQUEST.QUERY_STRING) formsemestre_id = sco_formsemestre_status.retreive_formsemestre_from_request( context, REQUEST ) # log('etud_info_html: formsemestre_id=%s' % formsemestre_id) with_photo = int(with_photo) etud = scolars.get_etud_info(filled=1, REQUEST=REQUEST)[0] photo_html = sco_photos.etud_photo_html( context, etud, title="fiche de " + etud["nom"], REQUEST=REQUEST ) # experimental: may be too slow to be here etud["codeparcours"], etud["decisions_jury"] = sco_report.get_codeparcoursetud( context.Notes, etud, prefix="S", separator=", " ) bac = sco_bac.Baccalaureat(etud["bac"], etud["specialite"]) etud["bac_abbrev"] = bac.abbrev() H = ( """
    %(nomprenom)s
    Bac: %(bac_abbrev)s
    %(codeparcours)s
    """ % etud ) # Informations sur l'etudiant dans le semestre courant: sem = None if formsemestre_id: # un semestre est spécifié par la page sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) elif etud["cursem"]: # le semestre "en cours" pour l'étudiant sem = etud["cursem"] if sem: groups = sco_groups.get_etud_groups(context, etudid, sem) grc = sco_groups.listgroups_abbrev(groups) H += '
    En S%d: %s
    ' % (sem["semestre_id"], grc) H += "
    " # fin partie gauche (eid_left) if with_photo: H += '' + photo_html + "" H += "
    " if debug: return ( html_sco_header.standard_html_header() + H + html_sco_header.standard_html_footer() ) else: return H