2020-09-26 16:19:37 +02:00
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
2022-01-01 14:49:42 +01:00
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
2020-09-26 16:19:37 +02:00
#
# 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
#
##############################################################################
""" Edition des PV de jury
2021-06-19 23:21:37 +02:00
PV Jury IUTV 2006 : on détaillait 8 cas :
2020-09-26 16:19:37 +02:00
Jury de semestre n
On a 8 types de décisions :
Passages :
1. passage de ceux qui ont validés Sn - 1
2. passage avec compensation Sn - 1 , Sn
3. passage sans validation de Sn avec validation d ' UE
4. passage sans validation de Sn sans validation d ' UE
Redoublements :
5. redoublement de Sn - 1 et Sn sans validation d ' UE pour Sn
6. redoublement de Sn - 1 et Sn avec validation d ' UE pour Sn
Reports
7. report sans validation d ' UE
8. non validation de Sn - 1 et Sn et non redoublement
"""
2021-06-19 23:21:37 +02:00
import time
2021-07-09 23:19:30 +02:00
from operator import itemgetter
2021-06-19 23:21:37 +02:00
from reportlab . platypus import Paragraph
from reportlab . lib import styles
2021-08-01 10:16:16 +02:00
import flask
2021-09-18 10:10:02 +02:00
from flask import url_for , g , request
2021-07-11 17:37:12 +02:00
2021-06-19 23:21:37 +02:00
import app . scodoc . sco_utils as scu
import app . scodoc . notesdb as ndb
2021-08-29 19:57:32 +02:00
from app import log
2021-06-19 23:21:37 +02:00
from app . scodoc import html_sco_header
from app . scodoc import sco_codes_parcours
2021-07-19 19:53:01 +02:00
from app . scodoc import sco_cache
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_edit_ue
from app . scodoc import sco_formations
from app . scodoc import sco_formsemestre
from app . scodoc import sco_groups
from app . scodoc import sco_groups_view
from app . scodoc import sco_parcours_dut
from app . scodoc import sco_pdf
from app . scodoc import sco_preferences
from app . scodoc import sco_pvpdf
from app . scodoc import sco_etud
from app . scodoc . gen_tables import GenTable
from app . scodoc . sco_codes_parcours import NO_SEMESTRE_ID
from app . scodoc . sco_pdf import PDFLOCK
from app . scodoc . TrivialFormulator import TrivialFormulator
2020-09-26 16:19:37 +02:00
2021-08-21 00:24:51 +02:00
def _descr_decisions_ues ( nt , etudid , decisions_ue , decision_sem ) :
2020-10-13 16:01:38 +02:00
""" Liste des UE validées dans ce semestre """
2020-09-26 16:19:37 +02:00
if not decisions_ue :
return [ ]
uelist = [ ]
# Les UE validées dans ce semestre:
for ue_id in decisions_ue . keys ( ) :
try :
if decisions_ue [ ue_id ] and (
2021-02-03 22:00:41 +01:00
decisions_ue [ ue_id ] [ " code " ] == sco_codes_parcours . ADM
2020-09-26 16:19:37 +02:00
or (
2021-07-19 19:53:01 +02:00
# XXX ceci devrait dépendre du parcours et non pas être une option ! #sco8
2021-02-13 19:20:21 +01:00
scu . CONFIG . CAPITALIZE_ALL_UES
2020-09-26 16:19:37 +02:00
and sco_codes_parcours . code_semestre_validant ( decision_sem [ " code " ] )
)
) :
2021-10-17 23:19:26 +02:00
ue = sco_edit_ue . ue_list ( args = { " ue_id " : ue_id } ) [ 0 ]
2020-09-26 16:19:37 +02:00
uelist . append ( ue )
except :
log ( " descr_decisions_ues: ue_id= %s decisions_ue= %s " % ( ue_id , decisions_ue ) )
# Les UE capitalisées dans d'autres semestres:
for ue in nt . ue_capitalisees [ etudid ] :
try :
uelist . append ( nt . get_etud_ue_status ( etudid , ue [ " ue_id " ] ) [ " ue " ] )
except KeyError :
pass
2021-07-10 13:58:25 +02:00
uelist . sort ( key = itemgetter ( " numero " ) )
2020-09-26 16:19:37 +02:00
return uelist
2021-08-21 00:24:51 +02:00
def _descr_decision_sem ( etat , decision_sem ) :
2020-09-26 16:19:37 +02:00
" résumé textuel de la décision de semestre "
if etat == " D " :
decision = " Démission "
else :
if decision_sem :
cod = decision_sem [ " code " ]
decision = sco_codes_parcours . CODES_EXPL . get ( cod , " " ) # + ' (%s)' % cod
else :
decision = " "
return decision
2021-08-21 00:24:51 +02:00
def _descr_decision_sem_abbrev ( etat , decision_sem ) :
2020-09-26 16:19:37 +02:00
" résumé textuel tres court (code) de la décision de semestre "
if etat == " D " :
decision = " Démission "
else :
if decision_sem :
decision = decision_sem [ " code " ]
else :
decision = " "
return decision
2021-08-21 00:24:51 +02:00
def descr_autorisations ( autorisations ) :
2020-09-26 16:19:37 +02:00
" résumé textuel des autorisations d ' inscription (-> ' S1, S3 ' ) "
alist = [ ]
for aut in autorisations :
alist . append ( " S " + str ( aut [ " semestre_id " ] ) )
return " , " . join ( alist )
2022-02-06 16:09:17 +01:00
def _comp_ects_by_ue_code ( nt , decision_ues ) :
2020-09-26 16:19:37 +02:00
""" Calcul somme des ECTS validés dans ce semestre (sans les UE capitalisées)
decision_ues est le resultat de nt . get_etud_decision_ues
Chaque resultat est un dict : { ue_code : ects }
"""
2022-02-06 16:09:17 +01:00
raise NotImplementedError ( ) # XXX #sco92
# ré-écrire en utilisant
2020-09-26 16:19:37 +02:00
if not decision_ues :
2022-02-06 16:09:17 +01:00
return { }
2020-09-26 16:19:37 +02:00
ects_by_ue_code = { }
for ue_id in decision_ues :
d = decision_ues [ ue_id ]
ue = nt . uedict [ ue_id ]
ects_by_ue_code [ ue [ " ue_code " ] ] = d [ " ects " ]
2022-02-06 16:09:17 +01:00
return ects_by_ue_code
2020-09-26 16:19:37 +02:00
def _comp_ects_capitalises_by_ue_code ( nt , etudid ) :
2020-10-13 16:01:38 +02:00
""" Calcul somme des ECTS des UE capitalisees """
2021-12-24 00:08:25 +01:00
ues = nt . get_ues_stat_dict ( )
2020-09-26 16:19:37 +02:00
ects_by_ue_code = { }
for ue in ues :
ue_status = nt . get_etud_ue_status ( etudid , ue [ " ue_id " ] )
if ue_status [ " is_capitalized " ] :
try :
ects_val = float ( ue_status [ " ue " ] [ " ects " ] )
except ( ValueError , TypeError ) :
ects_val = 0.0
ects_by_ue_code [ ue [ " ue_code " ] ] = ects_val
return ects_by_ue_code
def _sum_ects_dicts ( s , t ) :
""" Somme deux dictionnaires { ue_code : ects },
quand une UE de même code apparait deux fois , prend celle avec le plus d ' ECTS.
"""
sum_ects = sum ( s . values ( ) ) + sum ( t . values ( ) )
for ue_code in set ( s ) . intersection ( set ( t ) ) :
sum_ects - = min ( s [ ue_code ] , t [ ue_code ] )
return sum_ects
def dict_pvjury (
formsemestre_id ,
etudids = None ,
with_prev = False ,
with_parcours_decisions = False ,
) :
""" Données pour édition jury
etudids == None = > tous les inscrits , sinon donne la liste des ids
Si with_prev : ajoute infos sur code jury semestre precedent
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 ,
' 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
}
]
} ,
2020-10-13 16:01:38 +02:00
' decisions_dict ' : { etudid : decision ( comme ci - dessus ) } ,
}
2020-09-26 16:19:37 +02:00
"""
2021-07-19 19:53:01 +02:00
nt = sco_cache . NotesTableCache . get (
formsemestre_id
2020-09-26 16:19:37 +02:00
) # > get_etudids, get_etud_etat, get_etud_decision_sem, get_etud_decision_ues
if etudids is None :
etudids = nt . get_etudids ( )
if not etudids :
return { }
2021-06-15 13:59:56 +02:00
cnx = ndb . GetDBConnexion ( )
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
max_date = " 0000-01-01 "
has_prev = False # vrai si au moins un etudiant a un code prev
semestre_non_terminal = False # True si au moins un etudiant a un devenir
L = [ ]
D = { } # même chose que L, mais { etudid : dec }
for etudid in etudids :
2021-06-19 23:21:37 +02:00
etud = sco_etud . get_etud_info ( etudid = etudid , filled = True ) [ 0 ]
2021-08-19 10:28:35 +02:00
Se = sco_parcours_dut . SituationEtudParcours ( etud , formsemestre_id )
2020-09-26 16:19:37 +02:00
semestre_non_terminal = semestre_non_terminal or Se . semestre_non_terminal
d = { }
d [ " identite " ] = nt . identdict [ etudid ]
d [ " etat " ] = nt . get_etud_etat (
etudid
) # I|D|DEF (inscription ou démission ou défaillant)
d [ " decision_sem " ] = nt . get_etud_decision_sem ( etudid )
d [ " decisions_ue " ] = nt . get_etud_decision_ues ( etudid )
d [ " last_formsemestre_id " ] = Se . get_semestres ( ) [
- 1
] # id du dernier semestre (chronologiquement) dans lequel il a été inscrit
ects_capitalises_by_ue_code = _comp_ects_capitalises_by_ue_code ( nt , etudid )
d [ " sum_ects_capitalises " ] = sum ( ects_capitalises_by_ue_code . values ( ) )
2022-02-06 16:09:17 +01:00
ects_by_ue_code = _comp_ects_by_ue_code ( nt , d [ " decisions_ue " ] )
2020-09-26 16:19:37 +02:00
d [ " sum_ects " ] = _sum_ects_dicts ( ects_capitalises_by_ue_code , ects_by_ue_code )
if d [ " decision_sem " ] and sco_codes_parcours . code_semestre_validant (
d [ " decision_sem " ] [ " code " ]
) :
2021-02-04 20:02:44 +01:00
d [ " mention " ] = scu . get_mention ( nt . get_etud_moy_gen ( etudid ) )
2020-09-26 16:19:37 +02:00
else :
d [ " mention " ] = " "
# Versions "en français": (avec les UE capitalisées d'ailleurs)
dec_ue_list = _descr_decisions_ues (
2021-08-21 00:24:51 +02:00
nt , etudid , d [ " decisions_ue " ] , d [ " decision_sem " ]
2020-09-26 16:19:37 +02:00
)
d [ " decisions_ue_nb " ] = len (
dec_ue_list
) # avec les UE capitalisées, donc des éventuels doublons
# Mais sur la description (eg sur les bulletins), on ne veut pas
# afficher ces doublons: on uniquifie sur ue_code
_codes = set ( )
ue_uniq = [ ]
for ue in dec_ue_list :
if ue [ " ue_code " ] not in _codes :
ue_uniq . append ( ue )
_codes . add ( ue [ " ue_code " ] )
d [ " decisions_ue_descr " ] = " , " . join ( [ ue [ " acronyme " ] for ue in ue_uniq ] )
2021-08-21 00:24:51 +02:00
d [ " decision_sem_descr " ] = _descr_decision_sem ( d [ " etat " ] , d [ " decision_sem " ] )
2020-09-26 16:19:37 +02:00
d [ " autorisations " ] = sco_parcours_dut . formsemestre_get_autorisation_inscription (
2021-08-21 00:24:51 +02:00
etudid , formsemestre_id
2020-09-26 16:19:37 +02:00
)
2021-08-21 00:24:51 +02:00
d [ " autorisations_descr " ] = descr_autorisations ( d [ " autorisations " ] )
2020-09-26 16:19:37 +02:00
d [ " validation_parcours " ] = Se . parcours_validated ( )
d [ " parcours " ] = Se . get_parcours_descr ( filter_futur = True )
if with_parcours_decisions :
d [ " parcours_decisions " ] = Se . get_parcours_decisions ( )
# Observations sur les compensations:
compensators = sco_parcours_dut . scolar_formsemestre_validation_list (
cnx , args = { " compense_formsemestre_id " : formsemestre_id , " etudid " : etudid }
)
obs = [ ]
for compensator in compensators :
# nb: il ne devrait y en avoir qu'un !
2021-08-19 10:28:35 +02:00
csem = sco_formsemestre . get_formsemestre ( compensator [ " formsemestre_id " ] )
2020-09-26 16:19:37 +02:00
obs . append (
" %s compensé par %s ( %s ) "
% ( sem [ " sem_id_txt " ] , csem [ " sem_id_txt " ] , csem [ " anneescolaire " ] )
)
if d [ " decision_sem " ] and d [ " decision_sem " ] [ " compense_formsemestre_id " ] :
compensed = sco_formsemestre . get_formsemestre (
2021-08-19 10:28:35 +02:00
d [ " decision_sem " ] [ " compense_formsemestre_id " ]
2020-09-26 16:19:37 +02:00
)
obs . append (
" %s compense %s ( %s ) "
% (
sem [ " sem_id_txt " ] ,
compensed [ " sem_id_txt " ] ,
compensed [ " anneescolaire " ] ,
)
)
d [ " observation " ] = " , " . join ( obs )
# Cherche la date de decision (sem ou UE) la plus récente:
if d [ " decision_sem " ] :
2021-02-03 22:00:41 +01:00
date = ndb . DateDMYtoISO ( d [ " decision_sem " ] [ " event_date " ] )
2021-08-30 23:28:15 +02:00
if date and date > max_date : # decision plus recente
2020-09-26 16:19:37 +02:00
max_date = date
if d [ " decisions_ue " ] :
for dec_ue in d [ " decisions_ue " ] . values ( ) :
if dec_ue :
2021-02-03 22:00:41 +01:00
date = ndb . DateDMYtoISO ( dec_ue [ " event_date " ] )
2021-08-30 23:28:15 +02:00
if date and date > max_date : # decision plus recente
2020-09-26 16:19:37 +02:00
max_date = date
# Code semestre precedent
if with_prev : # optionnel car un peu long...
2021-06-19 23:21:37 +02:00
info = sco_etud . get_etud_info ( etudid = etudid , filled = True )
2020-09-26 16:19:37 +02:00
if not info :
continue # should not occur
etud = info [ 0 ]
if Se . prev and Se . prev_decision :
d [ " prev_decision_sem " ] = Se . prev_decision
d [ " prev_code " ] = Se . prev_decision [ " code " ]
2021-08-21 00:24:51 +02:00
d [ " prev_code_descr " ] = _descr_decision_sem ( " I " , Se . prev_decision )
2020-09-26 16:19:37 +02:00
d [ " prev " ] = Se . prev
has_prev = True
else :
d [ " prev_decision_sem " ] = None
d [ " prev_code " ] = " "
d [ " prev_code_descr " ] = " "
d [ " Se " ] = Se
L . append ( d )
D [ etudid ] = d
return {
2021-02-03 22:00:41 +01:00
" date " : ndb . DateISOtoDMY ( max_date ) ,
2020-09-26 16:19:37 +02:00
" formsemestre " : sem ,
" has_prev " : has_prev ,
" semestre_non_terminal " : semestre_non_terminal ,
2021-06-19 23:21:37 +02:00
" formation " : sco_formations . formation_list (
2021-08-19 10:28:35 +02:00
args = { " formation_id " : sem [ " formation_id " ] }
2021-06-19 23:21:37 +02:00
) [ 0 ] ,
2020-09-26 16:19:37 +02:00
" decisions " : L ,
" decisions_dict " : D ,
}
def pvjury_table (
dpv ,
only_diplome = False ,
anonymous = False ,
with_parcours_decisions = False ,
with_paragraph_nom = False , # cellule paragraphe avec nom, date, code NIP
) :
""" idem mais rend list de dicts
Si only_diplome , n ' extrait que les etudiants qui valident leur diplome.
"""
sem = dpv [ " formsemestre " ]
formsemestre_id = sem [ " formsemestre_id " ]
sem_id_txt_sp = sem [ " sem_id_txt " ]
if sem_id_txt_sp :
sem_id_txt_sp = " " + sem_id_txt_sp
titles = {
" etudid " : " etudid " ,
" code_nip " : " NIP " ,
" nomprenom " : " Nom " , # si with_paragraph_nom, sera un Paragraph
" parcours " : " Parcours " ,
" decision " : " Décision " + sem_id_txt_sp ,
" mention " : " Mention " ,
" ue_cap " : " UE " + sem_id_txt_sp + " capitalisées " ,
" ects " : " ECTS " ,
" devenir " : " Devenir " ,
2020-10-13 16:01:38 +02:00
" validation_parcours_code " : " Résultat au diplôme " ,
2020-09-26 16:19:37 +02:00
" observations " : " Observations " ,
}
if anonymous :
titles [ " nomprenom " ] = " Code "
columns_ids = [ " nomprenom " , " parcours " ]
if with_parcours_decisions :
all_idx = set ( )
for e in dpv [ " decisions " ] :
all_idx | = set ( e [ " parcours_decisions " ] . keys ( ) )
sem_ids = sorted ( all_idx )
for i in sem_ids :
if i != NO_SEMESTRE_ID :
titles [ i ] = " S %d " % i
else :
titles [ i ] = " S " # pas très parlant ?
columns_ids + = [ i ]
if dpv [ " has_prev " ] :
id_prev = sem [ " semestre_id " ] - 1 # numero du semestre precedent
titles [ " prev_decision " ] = " Décision S %s " % id_prev
columns_ids + = [ " prev_decision " ]
columns_ids + = [ " decision " ]
2021-07-28 17:03:54 +02:00
if sco_preferences . get_preference ( " bul_show_mention " , formsemestre_id ) :
2020-09-26 16:19:37 +02:00
columns_ids + = [ " mention " ]
columns_ids + = [ " ue_cap " ]
2021-07-28 17:03:54 +02:00
if sco_preferences . get_preference ( " bul_show_ects " , formsemestre_id ) :
2020-09-26 16:19:37 +02:00
columns_ids + = [ " ects " ]
2020-10-13 16:01:38 +02:00
2021-02-13 19:20:21 +01:00
# XXX if not dpv["semestre_non_terminal"]:
# La colonne doit être présente: redoublants validant leur diplome
# en répétant un semestre ancien: exemple: S1 (ADM), S2 (ADM), S3 (AJ), S4 (ADM), S3 (ADM)=> diplôme
columns_ids + = [ " validation_parcours_code " ]
columns_ids + = [ " devenir " ]
2020-09-26 16:19:37 +02:00
columns_ids + = [ " observations " ]
lines = [ ]
for e in dpv [ " decisions " ] :
2021-06-19 23:21:37 +02:00
sco_etud . format_etud_ident ( e [ " identite " ] )
2020-09-26 16:19:37 +02:00
l = {
" etudid " : e [ " identite " ] [ " etudid " ] ,
" code_nip " : e [ " identite " ] [ " code_nip " ] ,
" nomprenom " : e [ " identite " ] [ " nomprenom " ] ,
2021-07-11 17:37:12 +02:00
" _nomprenom_target " : url_for (
" scolar.ficheEtud " ,
scodoc_dept = g . scodoc_dept ,
etudid = e [ " identite " ] [ " etudid " ] ,
) ,
2020-09-26 16:19:37 +02:00
" _nomprenom_td_attrs " : ' id= " %s " class= " etudinfo " ' % e [ " identite " ] [ " etudid " ] ,
" parcours " : e [ " parcours " ] ,
2021-08-21 00:24:51 +02:00
" decision " : _descr_decision_sem_abbrev ( e [ " etat " ] , e [ " decision_sem " ] ) ,
2020-09-26 16:19:37 +02:00
" ue_cap " : e [ " decisions_ue_descr " ] ,
2021-02-13 19:20:21 +01:00
" validation_parcours_code " : " ADM " if e [ " validation_parcours " ] else " " ,
2020-09-26 16:19:37 +02:00
" devenir " : e [ " autorisations_descr " ] ,
2021-02-03 22:00:41 +01:00
" observations " : ndb . unquote ( e [ " observation " ] ) ,
2020-09-26 16:19:37 +02:00
" mention " : e [ " mention " ] ,
" ects " : str ( e [ " sum_ects " ] ) ,
}
if with_paragraph_nom :
cell_style = styles . ParagraphStyle ( { } )
2021-06-13 23:37:14 +02:00
cell_style . fontSize = sco_preferences . get_preference (
2021-07-28 17:03:54 +02:00
" SCOLAR_FONT_SIZE " , formsemestre_id
2020-09-26 16:19:37 +02:00
)
2021-06-13 23:37:14 +02:00
cell_style . fontName = sco_preferences . get_preference (
2021-07-28 17:03:54 +02:00
" PV_FONTNAME " , formsemestre_id
2021-06-13 23:37:14 +02:00
)
cell_style . leading = 1.0 * sco_preferences . get_preference (
2021-07-28 17:03:54 +02:00
" SCOLAR_FONT_SIZE " , formsemestre_id
2020-09-26 16:19:37 +02:00
) # vertical space
i = e [ " identite " ]
l [ " nomprenom " ] = [
2021-02-13 19:20:21 +01:00
Paragraph ( sco_pdf . SU ( i [ " nomprenom " ] ) , cell_style ) ,
Paragraph ( sco_pdf . SU ( i [ " code_nip " ] ) , cell_style ) ,
2020-09-26 16:19:37 +02:00
Paragraph (
2021-02-13 19:20:21 +01:00
sco_pdf . SU (
2020-09-26 16:19:37 +02:00
" Né le %s " % i [ " date_naissance " ]
+ ( " à %s " % i [ " lieu_naissance " ] if i [ " lieu_naissance " ] else " " )
+ ( " ( %s ) " % i [ " dept_naissance " ] if i [ " dept_naissance " ] else " " )
) ,
cell_style ,
) ,
]
if anonymous :
# Mode anonyme: affiche INE ou sinon NIP, ou id
l [ " nomprenom " ] = (
e [ " identite " ] [ " code_ine " ]
or e [ " identite " ] [ " code_nip " ]
or e [ " identite " ] [ " etudid " ]
)
if with_parcours_decisions :
for i in e [
" parcours_decisions "
] : # or equivalently: l.update(e['parcours_decisions'])
l [ i ] = e [ " parcours_decisions " ] [ i ]
if e [ " validation_parcours " ] :
l [ " devenir " ] = " Diplôme obtenu "
if dpv [ " has_prev " ] :
l [ " prev_decision " ] = _descr_decision_sem_abbrev (
2021-08-21 00:24:51 +02:00
None , e [ " prev_decision_sem " ]
2020-09-26 16:19:37 +02:00
)
if e [ " validation_parcours " ] or not only_diplome :
lines . append ( l )
return lines , titles , columns_ids
2021-09-27 10:20:10 +02:00
def formsemestre_pvjury ( formsemestre_id , format = " html " , publish = True ) :
2020-09-26 16:19:37 +02:00
""" Page récapitulant les décisions de jury
dpv : result of dict_pvjury
"""
2021-07-29 10:19:00 +02:00
footer = html_sco_header . sco_footer ( )
2020-09-26 16:19:37 +02:00
2021-08-21 00:24:51 +02:00
dpv = dict_pvjury ( formsemestre_id , with_prev = True )
2020-09-26 16:19:37 +02:00
if not dpv :
if format == " html " :
return (
2021-07-29 16:31:15 +02:00
html_sco_header . sco_header ( )
2020-09-26 16:19:37 +02:00
+ " <h2>Aucune information disponible !</h2> "
+ footer
)
else :
return None
sem = dpv [ " formsemestre " ]
formsemestre_id = sem [ " formsemestre_id " ]
2021-08-21 00:24:51 +02:00
rows , titles , columns_ids = pvjury_table ( dpv )
2020-09-26 16:19:37 +02:00
if format != " html " and format != " pdf " :
columns_ids = [ " etudid " , " code_nip " ] + columns_ids
tab = GenTable (
rows = rows ,
titles = titles ,
columns_ids = columns_ids ,
2021-02-04 20:02:44 +01:00
filename = scu . make_filename ( " decisions " + sem [ " titreannee " ] ) ,
2021-08-21 17:07:44 +02:00
origin = " Généré par %s le " % scu . sco_version . SCONAME
2021-02-13 19:20:21 +01:00
+ scu . timedate_human_repr ( )
+ " " ,
2020-09-26 16:19:37 +02:00
caption = " Décisions jury pour " + sem [ " titreannee " ] ,
html_class = " table_leftalign " ,
html_sortable = True ,
2021-07-28 17:03:54 +02:00
preferences = sco_preferences . SemPreferences ( formsemestre_id ) ,
2020-09-26 16:19:37 +02:00
)
if format != " html " :
return tab . make_page (
format = format ,
with_html_headers = False ,
publish = publish ,
)
2021-09-18 10:10:02 +02:00
tab . base_url = " %s ?formsemestre_id= %s " % ( request . base_url , formsemestre_id )
2020-09-26 16:19:37 +02:00
H = [
2021-06-13 19:12:20 +02:00
html_sco_header . html_sem_header (
2020-09-26 16:19:37 +02:00
" Décisions du jury pour le semestre " ,
init_qtip = True ,
javascripts = [ " js/etud_info.js " ] ,
) ,
""" <p>(dernière modif le %s )</p> """ % dpv [ " date " ] ,
]
H . append (
' <ul><li><a class= " stdlink " href= " formsemestre_lettres_individuelles?formsemestre_id= %s " >Courriers individuels (classeur pdf)</a></li> '
% formsemestre_id
)
H . append (
' <li><a class= " stdlink " href= " formsemestre_pvjury_pdf?formsemestre_id= %s " >PV officiel (pdf)</a></li></ul> '
% formsemestre_id
)
H . append ( tab . html ( ) )
# Count number of cases for each decision
2021-02-04 20:02:44 +01:00
counts = scu . DictDefault ( )
2020-09-26 16:19:37 +02:00
for row in rows :
counts [ row [ " decision " ] ] + = 1
# add codes for previous (for explanation, without count)
2021-07-09 17:47:06 +02:00
if " prev_decision " in row and row [ " prev_decision " ] :
2020-09-26 16:19:37 +02:00
counts [ row [ " prev_decision " ] ] + = 0
# Légende des codes
2022-01-22 12:15:03 +01:00
codes = list ( counts . keys ( ) )
2020-09-26 16:19:37 +02:00
codes . sort ( )
H . append ( " <h3>Explication des codes</h3> " )
lines = [ ]
for code in codes :
lines . append (
{
" code " : code ,
" count " : counts [ code ] ,
" expl " : sco_codes_parcours . CODES_EXPL . get ( code , " " ) ,
}
)
H . append (
GenTable (
rows = lines ,
titles = { " code " : " Code " , " count " : " Nombre " , " expl " : " " } ,
columns_ids = ( " code " , " count " , " expl " ) ,
html_class = " table_leftalign " ,
html_sortable = True ,
2021-07-28 17:03:54 +02:00
preferences = sco_preferences . SemPreferences ( formsemestre_id ) ,
2020-09-26 16:19:37 +02:00
) . html ( )
)
H . append ( " <p></p> " ) # force space at bottom
return " \n " . join ( H ) + footer
# ---------------------------------------------------------------------------
2021-09-27 10:20:10 +02:00
def formsemestre_pvjury_pdf ( formsemestre_id , group_ids = [ ] , etudid = None ) :
2020-09-26 16:19:37 +02:00
""" Generation PV jury en PDF: saisie des paramètres
Si etudid , PV pour un seul etudiant . Sinon , tout les inscrits au groupe indiqué .
"""
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2020-12-01 16:46:45 +01:00
# Mise à jour des groupes d'étapes:
2021-08-19 10:28:35 +02:00
sco_groups . create_etapes_partition ( formsemestre_id )
2020-09-26 16:19:37 +02:00
groups_infos = None
if etudid :
# PV pour ce seul étudiant:
2021-08-22 13:24:36 +02:00
etud = sco_etud . get_etud_info ( etudid = etudid , filled = True ) [ 0 ]
2020-09-26 16:19:37 +02:00
etuddescr = ' <a class= " discretelink " href= " ficheEtud?etudid= %s " > %s </a> ' % (
etudid ,
etud [ " nomprenom " ] ,
)
etudids = [ etudid ]
else :
etuddescr = " "
if not group_ids :
# tous les inscrits du semestre
2021-07-29 16:31:15 +02:00
group_ids = [ sco_groups . get_default_group ( formsemestre_id ) ]
2020-09-26 16:19:37 +02:00
groups_infos = sco_groups_view . DisplayedGroupsInfos (
2021-09-08 00:34:45 +02:00
group_ids , formsemestre_id = formsemestre_id
2020-09-26 16:19:37 +02:00
)
etudids = [ m [ " etudid " ] for m in groups_infos . members ]
H = [
2021-06-13 19:12:20 +02:00
html_sco_header . html_sem_header (
2020-09-26 16:19:37 +02:00
" Edition du PV de jury %s " % etuddescr ,
javascripts = sco_groups_view . JAVASCRIPTS ,
cssstyles = sco_groups_view . CSSSTYLES ,
init_qtip = True ,
) ,
""" <p class= " help " >Utiliser cette page pour éditer des versions provisoires des PV.
< span class = " fontred " > Il est recommandé d ' archiver les versions définitives: <a href= " formsemestre_archive?formsemestre_id= %s " >voir cette page</a></span>
< / p > """
% formsemestre_id ,
]
F = [
""" <p><em>Voir aussi si besoin les réglages sur la page " Paramétrage " (accessible à l ' administrateur du département).</em>
< / p > """ ,
2021-07-29 10:19:00 +02:00
html_sco_header . sco_footer ( ) ,
2020-09-26 16:19:37 +02:00
]
2021-08-20 10:51:42 +02:00
descr = descrform_pvjury ( sem )
2020-09-26 16:19:37 +02:00
if etudid :
descr . append ( ( " etudid " , { " input_type " : " hidden " } ) )
if groups_infos :
menu_choix_groupe = (
""" <div class= " group_ids_sel_menu " >Groupes d ' étudiants à lister sur le PV: """
2021-08-20 10:51:42 +02:00
+ sco_groups_view . menu_groups_choice ( groups_infos )
2020-09-26 16:19:37 +02:00
+ """ </div> """
)
else :
menu_choix_groupe = " " # un seul etudiant à editer
tf = TrivialFormulator (
2021-09-18 10:10:02 +02:00
request . base_url ,
2021-09-27 16:42:14 +02:00
scu . get_request_args ( ) ,
2020-09-26 16:19:37 +02:00
descr ,
cancelbutton = " Annuler " ,
method = " get " ,
submitlabel = " Générer document " ,
name = " tf " ,
formid = " group_selector " ,
html_foot_markup = menu_choix_groupe ,
)
if tf [ 0 ] == 0 :
return " \n " . join ( H ) + " \n " + tf [ 1 ] + " \n " . join ( F )
elif tf [ 0 ] == - 1 :
2021-07-31 18:01:10 +02:00
return flask . redirect (
2020-09-26 16:19:37 +02:00
" formsemestre_pvjury?formsemestre_id= %s " % ( formsemestre_id )
)
else :
# submit
2021-08-21 00:24:51 +02:00
dpv = dict_pvjury ( formsemestre_id , etudids = etudids , with_prev = True )
2020-09-26 16:19:37 +02:00
if tf [ 2 ] [ " showTitle " ] :
tf [ 2 ] [ " showTitle " ] = True
else :
tf [ 2 ] [ " showTitle " ] = False
if tf [ 2 ] [ " anonymous " ] :
tf [ 2 ] [ " anonymous " ] = True
else :
tf [ 2 ] [ " anonymous " ] = False
try :
PDFLOCK . acquire ( )
pdfdoc = sco_pvpdf . pvjury_pdf (
dpv ,
numeroArrete = tf [ 2 ] [ " numeroArrete " ] ,
VDICode = tf [ 2 ] [ " VDICode " ] ,
date_commission = tf [ 2 ] [ " date_commission " ] ,
date_jury = tf [ 2 ] [ " date_jury " ] ,
showTitle = tf [ 2 ] [ " showTitle " ] ,
2020-12-01 11:03:20 +01:00
pv_title = tf [ 2 ] [ " pv_title " ] ,
2020-09-26 16:19:37 +02:00
with_paragraph_nom = tf [ 2 ] [ " with_paragraph_nom " ] ,
anonymous = tf [ 2 ] [ " anonymous " ] ,
)
finally :
PDFLOCK . release ( )
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
dt = time . strftime ( " % Y- % m- %d " )
if groups_infos :
groups_filename = " - " + groups_infos . groups_filename
else :
groups_filename = " "
filename = " PV- %s %s - %s .pdf " % ( sem [ " titre_num " ] , groups_filename , dt )
2021-09-21 15:53:33 +02:00
return scu . sendPDFFile ( pdfdoc , filename )
2020-09-26 16:19:37 +02:00
2021-08-20 10:51:42 +02:00
def descrform_pvjury ( sem ) :
2020-10-13 16:01:38 +02:00
""" Définition de formulaire pour PV jury PDF """
2021-08-19 10:28:35 +02:00
F = sco_formations . formation_list ( formation_id = sem [ " formation_id " ] ) [ 0 ]
2020-09-26 16:19:37 +02:00
return [
(
" date_commission " ,
{
" input_type " : " text " ,
" size " : 50 ,
" title " : " Date de la commission " ,
" explanation " : " (format libre) " ,
} ,
) ,
(
" date_jury " ,
{
" input_type " : " text " ,
" size " : 50 ,
" title " : " Date du Jury " ,
" explanation " : " (si le jury a eu lieu) " ,
} ,
) ,
(
" numeroArrete " ,
{
" input_type " : " text " ,
" size " : 50 ,
" title " : " Numéro de l ' arrêté du président " ,
" explanation " : " le président de l ' Université prend chaque année un arrêté formant les jurys " ,
} ,
) ,
(
" VDICode " ,
{
" input_type " : " text " ,
" size " : 15 ,
" title " : " VDI et Code " ,
" explanation " : " VDI et code du diplôme Apogée (format libre, n ' est pas vérifié par ScoDoc) " ,
} ,
) ,
2020-12-01 11:03:20 +01:00
(
" pv_title " ,
{
" input_type " : " text " ,
" size " : 64 ,
" title " : " Titre du PV " ,
" explanation " : " par défaut, titre officiel de la formation " ,
" default " : F [ " titre_officiel " ] ,
} ,
) ,
2020-09-26 16:19:37 +02:00
(
" showTitle " ,
{
" input_type " : " checkbox " ,
2020-12-01 11:03:20 +01:00
" title " : " Indiquer en plus le titre du semestre sur le PV " ,
2020-09-26 16:19:37 +02:00
" explanation " : ' (le titre est " %s " ) ' % sem [ " titre " ] ,
" labels " : [ " " ] ,
" allowed_values " : ( " 1 " , ) ,
} ,
) ,
(
" with_paragraph_nom " ,
{
2021-02-05 21:34:26 +01:00
" input_type " : " boolcheckbox " ,
2020-09-26 16:19:37 +02:00
" title " : " Avec date naissance et code " ,
" explanation " : " ajoute informations sous le nom " ,
2021-02-05 21:34:26 +01:00
" default " : True ,
2020-09-26 16:19:37 +02:00
} ,
) ,
(
" anonymous " ,
{
" input_type " : " checkbox " ,
" title " : " PV anonyme " ,
" explanation " : " remplace nom par code étudiant (INE ou NIP) " ,
" labels " : [ " " ] ,
" allowed_values " : ( " 1 " , ) ,
} ,
) ,
( " formsemestre_id " , { " input_type " : " hidden " } ) ,
]
2021-09-27 10:20:10 +02:00
def formsemestre_lettres_individuelles ( formsemestre_id , group_ids = [ ] ) :
2020-09-26 16:19:37 +02:00
" Lettres avis jury en PDF "
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
if not group_ids :
# tous les inscrits du semestre
2021-07-29 16:31:15 +02:00
group_ids = [ sco_groups . get_default_group ( formsemestre_id ) ]
2020-09-26 16:19:37 +02:00
groups_infos = sco_groups_view . DisplayedGroupsInfos (
2021-09-08 00:34:45 +02:00
group_ids , formsemestre_id = formsemestre_id
2020-09-26 16:19:37 +02:00
)
etudids = [ m [ " etudid " ] for m in groups_infos . members ]
H = [
2021-06-13 19:12:20 +02:00
html_sco_header . html_sem_header (
2021-09-18 10:10:02 +02:00
" Édition des lettres individuelles " ,
2020-09-26 16:19:37 +02:00
javascripts = sco_groups_view . JAVASCRIPTS ,
cssstyles = sco_groups_view . CSSSTYLES ,
init_qtip = True ,
) ,
""" <p class= " help " >Utiliser cette page pour éditer des versions provisoires des PV.
< span class = " fontred " > Il est recommandé d ' archiver les versions définitives: <a href= " formsemestre_archive?formsemestre_id= %s " >voir cette page</a></span></p>
"""
% formsemestre_id ,
]
2021-07-29 10:19:00 +02:00
F = html_sco_header . sco_footer ( )
2020-09-26 16:19:37 +02:00
descr = descrform_lettres_individuelles ( )
menu_choix_groupe = (
""" <div class= " group_ids_sel_menu " >Groupes d ' étudiants à lister: """
2021-08-20 10:51:42 +02:00
+ sco_groups_view . menu_groups_choice ( groups_infos )
2020-09-26 16:19:37 +02:00
+ """ </div> """
)
tf = TrivialFormulator (
2021-09-18 10:10:02 +02:00
request . base_url ,
2021-09-27 16:42:14 +02:00
scu . get_request_args ( ) ,
2020-09-26 16:19:37 +02:00
descr ,
cancelbutton = " Annuler " ,
method = " POST " ,
submitlabel = " Générer document " ,
name = " tf " ,
formid = " group_selector " ,
html_foot_markup = menu_choix_groupe ,
)
if tf [ 0 ] == 0 :
return " \n " . join ( H ) + " \n " + tf [ 1 ] + F
elif tf [ 0 ] == - 1 :
2021-07-31 18:01:10 +02:00
return flask . redirect (
2020-09-26 16:19:37 +02:00
" formsemestre_pvjury?formsemestre_id= %s " % ( formsemestre_id )
)
else :
# submit
sf = tf [ 2 ] [ " signature " ]
signature = sf . read ( ) # image of signature
try :
PDFLOCK . acquire ( )
pdfdoc = sco_pvpdf . pdf_lettres_individuelles (
formsemestre_id ,
etudids = etudids ,
date_jury = tf [ 2 ] [ " date_jury " ] ,
date_commission = tf [ 2 ] [ " date_commission " ] ,
signature = signature ,
)
finally :
PDFLOCK . release ( )
if not pdfdoc :
2021-07-31 18:01:10 +02:00
return flask . redirect (
2021-05-11 11:48:32 +02:00
" formsemestre_status?formsemestre_id= {} &head_message=Aucun %20% C3 % A9tudiant % 20n %27a %20d e %20d % C3 % A9cision %20d e % 20jury " . format (
2020-09-26 16:19:37 +02:00
formsemestre_id
)
)
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
dt = time . strftime ( " % Y- % m- %d " )
groups_filename = " - " + groups_infos . groups_filename
filename = " lettres- %s %s - %s .pdf " % ( sem [ " titre_num " ] , groups_filename , dt )
2021-09-21 15:53:33 +02:00
return scu . sendPDFFile ( pdfdoc , filename )
2020-09-26 16:19:37 +02:00
def descrform_lettres_individuelles ( ) :
return [
(
" date_commission " ,
{
" input_type " : " text " ,
" size " : 50 ,
" title " : " Date de la commission " ,
" explanation " : " (format libre) " ,
} ,
) ,
(
" date_jury " ,
{
" input_type " : " text " ,
" size " : 50 ,
" title " : " Date du Jury " ,
" explanation " : " (si le jury a eu lieu) " ,
} ,
) ,
(
" signature " ,
{
" input_type " : " file " ,
" size " : 30 ,
" explanation " : " optionnel: image scannée de la signature " ,
} ,
) ,
( " formsemestre_id " , { " input_type " : " hidden " } ) ,
]