2020-09-26 16:19:37 +02:00
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
2023-01-02 13:16:27 +01:00
# Copyright (c) 1999 - 2023 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
#
##############################################################################
""" Semestres: validation semestre et UE dans parcours
"""
2021-10-11 22:22:42 +02:00
import time
2020-09-26 16:19:37 +02:00
2021-08-01 10:16:16 +02:00
import flask
2023-02-18 00:13:00 +01:00
from flask import url_for , flash , g , request
2022-04-07 23:31:08 +02:00
from app . models . etudiants import Identite
2021-07-11 17:37:12 +02:00
2021-06-19 23:21:37 +02:00
import app . scodoc . notesdb as ndb
import app . scodoc . sco_utils as scu
2022-07-06 00:05:14 +02:00
from app import db , log
2022-02-02 22:22:56 +01:00
from app . comp import res_sem
2022-03-27 22:25:00 +02:00
from app . comp . res_compat import NotesTableCompat
2023-06-23 10:37:32 +02:00
from app . models import Formation , FormSemestre , UniteEns , ScolarNews
2022-02-12 22:57:46 +01:00
from app . models . notes import etud_has_notes_attente
2022-07-06 00:05:14 +02:00
from app . models . validations import (
ScolarAutorisationInscription ,
ScolarFormSemestreValidation ,
)
from app . models . but_validations import ApcValidationRCUE , ApcValidationAnnee
2022-02-02 22:22:56 +01:00
from app . scodoc . sco_exceptions import ScoValueError
2021-06-19 23:21:37 +02:00
from app . scodoc . scolog import logdb
2023-02-12 13:36:47 +01:00
from app . scodoc . codes_cursus import *
2021-06-19 23:21:37 +02:00
from app . scodoc . TrivialFormulator import TrivialFormulator , tf_error_message
from app . scodoc import html_sco_header
2021-07-19 19:53:01 +02:00
from app . scodoc import sco_abs
2023-02-12 13:36:47 +01:00
from app . scodoc import codes_cursus
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_etud
from app . scodoc import sco_formsemestre
from app . scodoc import sco_formsemestre_inscriptions
2022-07-07 16:24:52 +02:00
from app . scodoc import sco_cursus
from app . scodoc import sco_cursus_dut
from app . scodoc . sco_cursus_dut import etud_est_inscrit_ue
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_photos
from app . scodoc import sco_preferences
2023-02-19 15:45:27 +01:00
from app . scodoc import sco_pv_dict
2020-09-26 16:19:37 +02:00
2023-06-15 08:49:05 +02:00
2020-09-26 16:19:37 +02:00
# ------------------------------------------------------------------------------------
def formsemestre_validation_etud_form (
formsemestre_id = None , # required
etudid = None , # one of etudid or etud_index is required
etud_index = None ,
check = 0 , # opt: si true, propose juste une relecture du parcours
2023-02-12 01:13:43 +01:00
dest_url = None ,
2020-09-26 16:19:37 +02:00
sortcol = None ,
2023-02-12 01:13:43 +01:00
read_only = True ,
2020-09-26 16:19:37 +02:00
) :
2022-10-03 19:13:15 +02:00
""" Formulaire de validation des décisions de jury """
formsemestre : FormSemestre = FormSemestre . query . filter_by (
id = formsemestre_id , dept_id = g . scodoc_dept_id
) . first_or_404 ( )
2023-03-20 11:17:38 +01:00
etud = Identite . get_etud ( etudid )
2022-02-12 22:57:46 +01:00
nt : NotesTableCompat = res_sem . load_formsemestre_results ( formsemestre )
2020-09-26 16:19:37 +02:00
T = nt . get_table_moyennes_triees ( )
2021-08-22 00:28:17 +02:00
if not etudid and etud_index is None :
2020-09-26 16:19:37 +02:00
raise ValueError ( " formsemestre_validation_etud_form: missing argument etudid " )
2021-08-22 00:28:17 +02:00
if etud_index is not None :
2020-09-26 16:19:37 +02:00
etud_index = int ( etud_index )
# cherche l'etudid correspondant
if etud_index < 0 or etud_index > = len ( T ) :
raise ValueError (
" formsemestre_validation_etud_form: invalid etud_index value "
)
etudid = T [ etud_index ] [ - 1 ]
else :
# cherche index pour liens navigation
etud_index = len ( T ) - 1
while etud_index > = 0 and T [ etud_index ] [ - 1 ] != etudid :
etud_index - = 1
if etud_index < 0 :
raise ValueError (
" formsemestre_validation_etud_form: can ' t retreive etud_index ! "
)
# prev, next pour liens navigation
etud_index_next = etud_index + 1
if etud_index_next > = len ( T ) :
etud_index_next = None
etud_index_prev = etud_index - 1
if etud_index_prev < 0 :
etud_index_prev = None
2023-02-12 01:13:43 +01:00
if read_only :
2020-09-26 16:19:37 +02:00
check = True
2021-06-19 23:21:37 +02:00
etud = sco_etud . get_etud_info ( etudid = etudid , filled = True ) [ 0 ]
2022-07-07 16:24:52 +02:00
Se = sco_cursus . get_situation_etud_cursus ( etud , formsemestre_id )
2021-08-10 12:57:38 +02:00
if not Se . sem [ " etat " ] :
2020-09-26 16:19:37 +02:00
raise ScoValueError ( " validation: semestre verrouille " )
2022-04-07 23:31:08 +02:00
url_tableau = url_for (
" notes.formsemestre_recapcomplet " ,
scodoc_dept = g . scodoc_dept ,
2022-06-29 16:30:01 +02:00
mode_jury = 1 ,
2022-04-07 23:31:08 +02:00
formsemestre_id = formsemestre_id ,
selected_etudid = etudid , # va a la bonne ligne
)
2020-09-26 16:19:37 +02:00
H = [
2021-06-13 23:37:14 +02:00
html_sco_header . sco_header (
2022-04-07 23:31:08 +02:00
page_title = f " Parcours { etud [ ' nomprenom ' ] } " ,
2020-09-26 16:19:37 +02:00
javascripts = [ " js/recap_parcours.js " ] ,
)
]
# Navigation suivant/precedent
2022-04-07 23:31:08 +02:00
if etud_index_prev is not None :
2023-03-20 11:17:38 +01:00
etud_prev = Identite . get_etud ( T [ etud_index_prev ] [ - 1 ] )
2022-04-07 23:31:08 +02:00
url_prev = url_for (
" notes.formsemestre_validation_etud_form " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre_id ,
etud_index = etud_index_prev ,
2020-09-26 16:19:37 +02:00
)
2022-04-07 23:31:08 +02:00
else :
url_prev = None
if etud_index_next is not None :
2023-03-20 11:17:38 +01:00
etud_next = Identite . get_etud ( T [ etud_index_next ] [ - 1 ] )
2022-04-07 23:31:08 +02:00
url_next = url_for (
" notes.formsemestre_validation_etud_form " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre_id ,
etud_index = etud_index_next ,
)
else :
url_next = None
footer = [ """ <div class= " jury_footer " ><span> """ ]
if url_prev :
footer . append (
f ' < <a class= " stdlink " href= " { url_prev } " > { etud_prev . nomprenom } </a> '
2020-09-26 16:19:37 +02:00
)
2022-04-07 23:31:08 +02:00
footer . append (
f """ </span><span><a class= " stdlink " href= " { url_tableau } " >retour à la liste</a></span><span> """
)
if url_next :
footer . append (
f ' <a class= " stdlink " href= " { url_next } " > { etud_next . nomprenom } </a> > '
)
footer . append ( " </span></div> " )
footer . append ( html_sco_header . sco_footer ( ) )
2020-09-26 16:19:37 +02:00
H . append ( ' <table style= " width: 100 % " ><tr><td> ' )
if not check :
H . append (
' <h2 class= " formsemestre " > %s : validation %s %s </h2>Parcours: %s '
% (
etud [ " nomprenom " ] ,
Se . parcours . SESSION_NAME_A ,
Se . parcours . SESSION_NAME ,
2023-02-12 13:36:47 +01:00
Se . get_cursus_descr ( ) ,
2020-09-26 16:19:37 +02:00
)
)
else :
H . append (
' <h2 class= " formsemestre " >Parcours de %s </h2> %s '
2023-02-12 13:36:47 +01:00
% ( etud [ " nomprenom " ] , Se . get_cursus_descr ( ) )
2020-09-26 16:19:37 +02:00
)
H . append (
2021-07-11 17:37:12 +02:00
' </td><td style= " text-align: right; " ><a href= " %s " > %s </a></td></tr></table> '
2020-09-26 16:19:37 +02:00
% (
2021-07-11 17:37:12 +02:00
url_for ( " scolar.ficheEtud " , scodoc_dept = g . scodoc_dept , etudid = etudid ) ,
2021-09-24 12:10:53 +02:00
sco_photos . etud_photo_html ( etud , title = " fiche de %s " % etud [ " nom " ] ) ,
2020-09-26 16:19:37 +02:00
)
)
etud_etat = nt . get_etud_etat ( etudid )
2022-09-30 22:43:39 +02:00
if etud_etat == scu . DEMISSION :
2020-09-26 16:19:37 +02:00
H . append ( ' <div class= " ue_warning " ><span>Etudiant démissionnaire</span></div> ' )
2022-09-30 22:43:39 +02:00
if etud_etat == scu . DEF :
2020-09-26 16:19:37 +02:00
H . append ( ' <div class= " ue_warning " ><span>Etudiant défaillant</span></div> ' )
2022-09-30 22:43:39 +02:00
if etud_etat != scu . INSCRIT :
2020-09-26 16:19:37 +02:00
H . append (
2022-10-03 19:13:15 +02:00
f """
< div class = " warning " >
Impossible de statuer sur cet étudiant :
2021-09-28 07:27:55 +02:00
il est démissionnaire ou défaillant ( voir < a href = " {
url_for ( " scolar.ficheEtud " , scodoc_dept = g . scodoc_dept , etudid = etudid )
} " >sa fiche</a>)
2022-10-03 19:13:15 +02:00
< / div >
"""
2020-09-26 16:19:37 +02:00
)
2022-04-07 23:31:08 +02:00
return " \n " . join ( H + footer )
2020-09-26 16:19:37 +02:00
H . append (
formsemestre_recap_parcours_table (
2023-02-12 01:13:43 +01:00
Se , etudid , with_links = ( check and not read_only )
2020-09-26 16:19:37 +02:00
)
)
if check :
2023-02-12 01:13:43 +01:00
if not dest_url :
dest_url = url_tableau
H . append ( f ' <ul><li><a href= " { dest_url } " >Continuer</a></li></ul> ' )
2020-09-26 16:19:37 +02:00
2022-04-07 23:31:08 +02:00
return " \n " . join ( H + footer )
2020-09-26 16:19:37 +02:00
decision_jury = Se . nt . get_etud_decision_sem ( etudid )
# Bloque si note en attente
2022-02-12 22:57:46 +01:00
if etud_has_notes_attente ( etudid , formsemestre_id ) :
2020-09-26 16:19:37 +02:00
H . append (
tf_error_message (
2021-09-28 07:27:55 +02:00
f """ Impossible de statuer sur cet étudiant: il a des notes en
attente dans des évaluations de ce semestre ( voir < a href = " {
url_for ( " notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre_id )
} " >tableau de bord</a>)
"""
2020-09-26 16:19:37 +02:00
)
)
2022-04-07 23:31:08 +02:00
return " \n " . join ( H + footer )
2020-09-26 16:19:37 +02:00
# Infos si pas de semestre précédent
if not Se . prev :
if Se . sem [ " semestre_id " ] == 1 :
H . append ( " <p>Premier semestre (pas de précédent)</p> " )
else :
H . append ( " <p>Pas de semestre précédent !</p> " )
else :
if not Se . prev_decision :
H . append (
tf_error_message (
2021-09-28 07:27:55 +02:00
f """ Le jury n ' a pas statué sur le semestre précédent ! (<a href= " {
url_for ( " notes.formsemestre_validation_etud_form " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = Se . prev [ " formsemestre_id " ] ,
etudid = etudid )
} " >le faire maintenant</a>)
"""
2020-09-26 16:19:37 +02:00
)
)
if decision_jury :
H . append (
2021-09-28 07:27:55 +02:00
f """ <a href= " {
url_for ( " notes.formsemestre_validation_suppress_etud " ,
scodoc_dept = g . scodoc_dept ,
etudid = etudid , formsemestre_id = formsemestre_id
)
} " class= " stdlink " >Supprimer décision existante</a>
"""
2020-09-26 16:19:37 +02:00
)
2021-07-29 10:19:00 +02:00
H . append ( html_sco_header . sco_footer ( ) )
2020-09-26 16:19:37 +02:00
return " \n " . join ( H )
# Infos sur decisions déjà saisies
if decision_jury :
if decision_jury [ " assidu " ] :
ass = " assidu "
else :
ass = " non assidu "
H . append ( " <p>Décision existante du %(event_date)s : %(code)s " % decision_jury )
H . append ( " ( %s ) " % ass )
2022-07-07 16:24:52 +02:00
autorisations = ScolarAutorisationInscription . query . filter_by (
etudid = etudid , origin_formsemestre_id = formsemestre_id
) . all ( )
if autorisations :
2020-09-26 16:19:37 +02:00
H . append ( " . Autorisé %s à s ' inscrire en " % etud [ " ne " ] )
2022-07-07 16:24:52 +02:00
H . append ( " , " . join ( [ f " S { aut . semestre_id } " for aut in autorisations ] ) + " . " )
2020-09-26 16:19:37 +02:00
H . append ( " </p> " )
# Cas particulier pour ATJ: corriger precedent avant de continuer
if Se . prev_decision and Se . prev_decision [ " code " ] == ATJ :
H . append (
""" <div class= " sfv_warning " ><p>La décision du semestre précédent est en
< b > attente < / b > à cause d \' un <b>problème d \' assiduité<b>.</p>
< p > Vous devez la corriger avant de continuer ce jury . Soit vous considérez que le
problème d ' assiduité n ' est pas réglé et choisissez de ne pas valider le semestre
précédent ( échec ) , soit vous entrez une décision sans prendre en compte
l ' assiduité.</p>
< form method = " get " action = " formsemestre_validation_etud_form " >
< input type = " submit " value = " Statuer sur le semestre précédent " / >
< input type = " hidden " name = " formsemestre_id " value = " %s " / >
< input type = " hidden " name = " etudid " value = " %s " / >
2021-05-11 11:48:32 +02:00
< input type = " hidden " name = " desturl " value = " formsemestre_validation_etud_form?etudid= %s &formsemestre_id= %s " / >
2020-09-26 16:19:37 +02:00
"""
% ( Se . prev [ " formsemestre_id " ] , etudid , etudid , formsemestre_id )
)
if sortcol :
H . append ( ' <input type= " hidden " name= " sortcol " value= " %s " /> ' % sortcol )
H . append ( " </form></div> " )
2021-07-29 10:19:00 +02:00
H . append ( html_sco_header . sco_footer ( ) )
2020-09-26 16:19:37 +02:00
return " \n " . join ( H )
# Explication sur barres actuelles
H . append ( ' <p class= " sfv_explication " >L \' étudiant ' )
if Se . barre_moy_ok :
H . append ( " a la moyenne générale, " )
else :
H . append ( " <b>n ' a pas</b> la moyenne générale, " )
H . append ( Se . barres_ue_diag ) # eg 'les UEs sont au dessus des barres'
if ( not Se . barre_moy_ok ) and Se . can_compensate_with_prev :
H . append ( " , et ce semestre peut se <b>compenser</b> avec le précédent " )
H . append ( " .</p> " )
# Décisions possibles
rows_assidu = decisions_possible_rows (
2022-09-03 11:41:56 +02:00
Se , True , subtitle = " Étudiant assidu: " , trclass = " sfv_ass "
2020-09-26 16:19:37 +02:00
)
rows_non_assidu = decisions_possible_rows (
Se , False , subtitle = " Si problème d ' assiduité: " , trclass = " sfv_pbass "
)
# s'il y a des decisions recommandees issues des regles:
if rows_assidu or rows_non_assidu :
H . append (
""" <form method= " get " action= " formsemestre_validation_etud " id= " formvalid " class= " sfv_decisions " >
< input type = " hidden " name = " etudid " value = " %s " / >
< input type = " hidden " name = " formsemestre_id " value = " %s " / > """
% ( etudid , formsemestre_id )
)
2023-02-12 01:13:43 +01:00
if dest_url :
H . append ( ' <input type= " hidden " name= " desturl " value= " %s " /> ' % dest_url )
2020-09-26 16:19:37 +02:00
if sortcol :
H . append ( ' <input type= " hidden " name= " sortcol " value= " %s " /> ' % sortcol )
H . append ( ' <h3 class= " sfv " >Décisions <em>recommandées</em> :</h3> ' )
H . append ( " <table> " )
H . append ( rows_assidu )
if rows_non_assidu :
H . append ( " <tr><td> </td></tr> " ) # spacer
H . append ( rows_non_assidu )
H . append ( " </table> " )
H . append (
2022-10-02 23:43:29 +02:00
' <p><br></p><input type= " submit " value= " Valider ce choix " disabled= " 1 " id= " subut " /> '
2020-09-26 16:19:37 +02:00
)
H . append ( " </form> " )
2021-08-21 00:24:51 +02:00
H . append ( form_decision_manuelle ( Se , formsemestre_id , etudid ) )
2020-09-26 16:19:37 +02:00
H . append (
2021-08-30 23:28:15 +02:00
f """ <div class= " link_defaillance " >Ou <a class= " stdlink " href= " {
2022-09-30 22:43:39 +02:00
url_for ( " scolar.form_def " , scodoc_dept = g . scodoc_dept , etudid = etudid ,
2021-08-30 23:28:15 +02:00
formsemestre_id = formsemestre_id )
} " >déclarer l ' étudiant comme défaillant dans ce semestre</a></div> " " "
2020-09-26 16:19:37 +02:00
)
H . append ( ' <p style= " font-size: 50 % ; " >Formation ' )
2021-08-11 00:36:07 +02:00
if Se . sem [ " gestion_semestrielle " ] :
2020-09-26 16:19:37 +02:00
H . append ( " avec semestres décalés</p> " )
else :
H . append ( " sans semestres décalés</p> " )
2022-04-07 23:31:08 +02:00
return " " . join ( H + footer )
2020-09-26 16:19:37 +02:00
def formsemestre_validation_etud (
formsemestre_id = None , # required
etudid = None , # required
codechoice = None , # required
desturl = " " ,
sortcol = None ,
) :
""" Enregistre validation """
2021-06-19 23:21:37 +02:00
etud = sco_etud . get_etud_info ( etudid = etudid , filled = True ) [ 0 ]
2022-07-07 16:24:52 +02:00
Se = sco_cursus . get_situation_etud_cursus ( etud , formsemestre_id )
2020-09-26 16:19:37 +02:00
# retrouve la decision correspondant au code:
choices = Se . get_possible_choices ( assiduite = True )
choices + = Se . get_possible_choices ( assiduite = False )
2021-06-19 23:21:37 +02:00
selected_choice = None
2020-09-26 16:19:37 +02:00
for choice in choices :
if choice . codechoice == codechoice :
2021-06-19 23:21:37 +02:00
selected_choice = choice
2020-09-26 16:19:37 +02:00
break
2021-06-19 23:21:37 +02:00
if not selected_choice :
2020-09-26 16:19:37 +02:00
raise ValueError ( " code choix invalide ! ( %s ) " % codechoice )
#
2021-09-27 10:20:10 +02:00
Se . valide_decision ( selected_choice ) # enregistre
2021-02-07 15:31:35 +01:00
return _redirect_valid_choice (
2021-09-24 00:28:09 +02:00
formsemestre_id , etudid , Se , selected_choice , desturl , sortcol
2020-09-26 16:19:37 +02:00
)
def formsemestre_validation_etud_manu (
formsemestre_id = None , # required
etudid = None , # required
code_etat = " " ,
new_code_prev = " " ,
devenir = " " , # required (la decision manuelle)
assidu = False ,
desturl = " " ,
sortcol = None ,
redirect = True ,
) :
""" Enregistre validation """
if assidu :
2021-08-11 00:36:07 +02:00
assidu = True
2021-06-19 23:21:37 +02:00
etud = sco_etud . get_etud_info ( etudid = etudid , filled = True ) [ 0 ]
2022-07-07 16:24:52 +02:00
Se = sco_cursus . get_situation_etud_cursus ( etud , formsemestre_id )
2020-09-26 16:19:37 +02:00
if code_etat in Se . parcours . UNUSED_CODES :
raise ScoValueError ( " code decision invalide dans ce parcours " )
# Si code ADC, extrait le semestre utilisé:
if code_etat [ : 3 ] == ADC :
formsemestre_id_utilise_pour_compenser = code_etat . split ( " _ " ) [ 1 ]
if not formsemestre_id_utilise_pour_compenser :
formsemestre_id_utilise_pour_compenser = (
None # compense avec semestre hors ScoDoc
)
code_etat = ADC
else :
formsemestre_id_utilise_pour_compenser = None
# Construit le choix correspondant:
2022-07-07 16:24:52 +02:00
choice = sco_cursus_dut . DecisionSem (
2020-09-26 16:19:37 +02:00
code_etat = code_etat ,
new_code_prev = new_code_prev ,
devenir = devenir ,
assiduite = assidu ,
formsemestre_id_utilise_pour_compenser = formsemestre_id_utilise_pour_compenser ,
)
#
2021-09-27 10:20:10 +02:00
Se . valide_decision ( choice ) # enregistre
2020-09-26 16:19:37 +02:00
if redirect :
2021-02-07 15:31:35 +01:00
return _redirect_valid_choice (
2021-09-24 00:28:09 +02:00
formsemestre_id , etudid , Se , choice , desturl , sortcol
2020-09-26 16:19:37 +02:00
)
2021-09-24 00:28:09 +02:00
def _redirect_valid_choice ( formsemestre_id , etudid , Se , choice , desturl , sortcol ) :
2021-06-13 23:37:14 +02:00
adr = " formsemestre_validation_etud_form?formsemestre_id= %s &etudid= %s &check=1 " % (
formsemestre_id ,
etudid ,
2020-09-26 16:19:37 +02:00
)
if sortcol :
2021-09-24 00:28:09 +02:00
adr + = " &sortcol= " + str ( sortcol )
2021-02-07 15:31:35 +01:00
# if desturl:
2021-05-11 11:48:32 +02:00
# desturl += "&desturl=" + desturl
2021-07-31 18:01:10 +02:00
return flask . redirect ( adr )
2020-09-26 16:19:37 +02:00
# Si le precedent a été modifié, demande relecture du parcours.
# sinon renvoie au listing general,
def _dispcode ( c ) :
if not c :
return " "
return c
def decisions_possible_rows ( Se , assiduite , subtitle = " " , trclass = " " ) :
" Liste HTML des decisions possibles "
choices = Se . get_possible_choices ( assiduite = assiduite )
if not choices :
return " "
TitlePrev = " "
if Se . prev :
if Se . prev [ " semestre_id " ] > = 0 :
TitlePrev = " %s %d " % ( Se . parcours . SESSION_ABBRV , Se . prev [ " semestre_id " ] )
else :
TitlePrev = " Prec. "
if Se . sem [ " semestre_id " ] > = 0 :
TitleCur = " %s %d " % ( Se . parcours . SESSION_ABBRV , Se . sem [ " semestre_id " ] )
else :
TitleCur = Se . parcours . SESSION_NAME
H = [
' <tr class= " %s titles " ><th class= " sfv_subtitle " > %s </em></th> '
% ( trclass , subtitle )
]
if Se . prev :
H . append ( " <th>Code %s </th> " % TitlePrev )
H . append ( " <th>Code %s </th><th>Devenir</th></tr> " % TitleCur )
for ch in choices :
H . append (
""" <tr class= " %s " ><td title= " règle %s " ><input type= " radio " name= " codechoice " value= " %s " onClick= " document.getElementById( ' subut ' ).disabled=false; " > """
% ( trclass , ch . rule_id , ch . codechoice )
)
H . append ( " %s </input></td> " % ch . explication )
if Se . prev :
H . append ( ' <td class= " centercell " > %s </td> ' % _dispcode ( ch . new_code_prev ) )
H . append (
' <td class= " centercell " > %s </td><td> %s </td> '
% ( _dispcode ( ch . code_etat ) , Se . explique_devenir ( ch . devenir ) )
)
H . append ( " </tr> " )
return " \n " . join ( H )
def formsemestre_recap_parcours_table (
Se ,
etudid ,
with_links = False ,
with_all_columns = True ,
a_url = " " ,
2021-10-11 22:22:42 +02:00
sem_info = None ,
2020-09-26 16:19:37 +02:00
show_details = False ,
) :
""" Tableau HTML recap parcours
2021-01-01 18:40:47 +01:00
Si with_links , ajoute liens pour modifier decisions ( colonne de droite )
2020-09-26 16:19:37 +02:00
sem_info = { formsemestre_id : txt } permet d ' ajouter des informations associées à chaque semestre
with_all_columns : si faux , pas de colonne " assiduité " .
"""
2021-10-11 22:22:42 +02:00
sem_info = sem_info or { }
2020-09-26 16:19:37 +02:00
H = [ ]
linktmpl = ' <span onclick= " toggle_vis(this); " class= " toggle_sem sem_ %% s " > %s </span> '
2021-02-04 20:02:44 +01:00
minuslink = linktmpl % scu . icontag ( " minus_img " , border = " 0 " , alt = " - " )
pluslink = linktmpl % scu . icontag ( " plus_img " , border = " 0 " , alt = " + " )
2020-09-26 16:19:37 +02:00
if show_details :
sd = " recap_show_details "
plusminus = minuslink
else :
sd = " recap_hide_details "
plusminus = pluslink
H . append (
2023-02-17 21:22:54 +01:00
f """ <table class= " recap_parcours { sd } " >
< tr >
< th > < span onclick = " toggle_all_sems(this); "
title = " Ouvrir/fermer tous les semestres " > {
scu . icontag ( " plus18_img " , width = 18 , height = 18 , border = 0 , title = " " , alt = " + " )
} < / span > < / th >
< th > < / th >
< th > Semestre < / th >
< th > Etat < / th >
< th > Abs < / th >
"""
2020-09-26 16:19:37 +02:00
)
# titres des UE
H . append ( " <th></th> " * Se . nb_max_ue )
#
if with_links :
H . append ( " <th></th> " )
H . append ( " <th></th></tr> " )
2023-02-17 21:22:54 +01:00
num_sem = 0
2020-09-26 16:19:37 +02:00
for sem in Se . get_semestres ( ) :
is_prev = Se . prev and ( Se . prev [ " formsemestre_id " ] == sem [ " formsemestre_id " ] )
is_cur = Se . formsemestre_id == sem [ " formsemestre_id " ]
num_sem + = 1
2023-02-19 15:45:27 +01:00
dpv = sco_pv_dict . dict_pvjury ( sem [ " formsemestre_id " ] , etudids = [ etudid ] )
2020-09-26 16:19:37 +02:00
pv = dpv [ " decisions " ] [ 0 ]
decision_sem = pv [ " decision_sem " ]
decisions_ue = pv [ " decisions_ue " ]
2021-08-11 00:36:07 +02:00
if with_all_columns and decision_sem and not decision_sem [ " assidu " ] :
2020-09-26 16:19:37 +02:00
ass = " (non ass.) "
else :
ass = " "
2022-02-02 22:22:56 +01:00
formsemestre = FormSemestre . query . get ( sem [ " formsemestre_id " ] )
2022-02-06 16:09:17 +01:00
nt : NotesTableCompat = res_sem . load_formsemestre_results ( formsemestre )
2020-09-26 16:19:37 +02:00
if is_cur :
type_sem = " * " # now unused
class_sem = " sem_courant "
elif is_prev :
type_sem = " p "
class_sem = " sem_precedent "
else :
type_sem = " "
class_sem = " sem_autre "
2022-02-10 12:13:24 +01:00
if sem [ " formation_code " ] != Se . formation . formation_code :
2020-09-26 16:19:37 +02:00
class_sem + = " sem_autre_formation "
if sem [ " bul_bgcolor " ] :
bgcolor = sem [ " bul_bgcolor " ]
else :
bgcolor = " background-color: rgb(255,255,240) "
# 1ere ligne: titre sem, decision, acronymes UE
H . append ( ' <tr class= " %s rcp_l1 sem_ %s " > ' % ( class_sem , sem [ " formsemestre_id " ] ) )
if is_cur :
pm = " "
elif is_prev :
pm = minuslink % sem [ " formsemestre_id " ]
else :
pm = plusminus % sem [ " formsemestre_id " ]
2022-05-28 11:38:22 +02:00
inscr = formsemestre . etuds_inscriptions . get ( etudid )
2023-02-17 21:22:54 +01:00
parcours_name = " "
if inscr and nt . is_apc :
if inscr . parcour :
parcours_name = (
f ' <span class= " code_parcours " > { inscr . parcour . code } </span> '
)
else :
# si l'étudiant n'est pas inscrit à un parcours mais que le semestre a plus d'UE
# signale un éventuel problème:
2023-04-03 17:46:31 +02:00
if len ( nt . formsemestre . get_ues ( ) ) > len (
nt . etud_ues_ids ( etudid )
) : # XXX sans dispenses
2023-02-17 21:22:54 +01:00
parcours_name = f """
< span class = " code_parcours no_parcours " > { scu . EMO_WARNING } & nbsp ; pas de parcours
< / span > """
2020-09-26 16:19:37 +02:00
H . append (
2022-05-28 11:38:22 +02:00
f """
< td class = " rcp_type_sem " style = " background-color: {bgcolor} ; " > { num_sem } { pm } < / td >
< td class = " datedebut " > { sem [ ' mois_debut ' ] } < / td >
< td class = " rcp_titre_sem " > < a class = " formsemestre_status_link "
href = " {a_url} formsemestre_bulletinetud?formsemestre_id= {formsemestre.id} &etudid= {etudid} "
2023-01-26 16:35:15 +01:00
title = " Bulletin de notes " > { formsemestre . titre_annee ( ) } { parcours_name } < / a >
2022-05-28 11:38:22 +02:00
"""
2020-09-26 16:19:37 +02:00
)
2023-01-26 16:35:15 +01:00
if nt . is_apc :
H . append (
f """ <a class= " stdlink jury_link " title= " Validations du semestre BUT "
href = " { url_for( " notes . formsemestre_validation_but " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre . id ,
etudid = etudid ,
)
} " >jury</a> " " "
)
H . append ( """ </td> """ )
2022-06-30 20:43:09 +02:00
if nt . is_apc :
H . append ( ' <td class= " rcp_but " >BUT</td> ' )
elif decision_sem :
2022-11-27 19:07:42 +01:00
H . append (
f """ <td class= " rcp_dec " > {
decision_sem [ " code " ] } < / td > """
)
2020-09-26 16:19:37 +02:00
else :
2022-06-30 20:43:09 +02:00
H . append ( " <td><em>en cours</em></td> " )
2022-11-27 19:07:42 +01:00
H . append ( f """ <td class= " rcp_nonass " > { ass } </td> """ ) # abs
2022-02-27 20:12:20 +01:00
# acronymes UEs auxquelles l'étudiant est inscrit (ou capitalisé)
2022-11-27 19:07:42 +01:00
ues = list ( nt . etud_ues ( etudid ) )
2021-12-24 00:08:25 +01:00
cnx = ndb . GetDBConnexion ( )
2022-11-27 19:07:42 +01:00
etud_ue_status = { ue . id : nt . get_etud_ue_status ( etudid , ue . id ) for ue in ues }
2022-03-21 22:29:55 +01:00
if not nt . is_apc :
# formations classiques: filtre UE sur inscriptions (et garde UE capitalisées)
ues = [
ue
for ue in ues
2022-11-27 19:07:42 +01:00
if etud_est_inscrit_ue ( cnx , etudid , sem [ " formsemestre_id " ] , ue . id )
or etud_ue_status [ ue . id ] [ " is_capitalized " ]
2022-03-21 22:29:55 +01:00
]
2021-12-24 00:08:25 +01:00
2020-09-26 16:19:37 +02:00
for ue in ues :
2022-11-27 19:07:42 +01:00
H . append ( f """ <td class= " ue_acro " ><span> { ue . acronyme } </span></td> """ )
2020-09-26 16:19:37 +02:00
if len ( ues ) < Se . nb_max_ue :
2022-11-27 19:07:42 +01:00
H . append ( f """ <td colspan= " { Se . nb_max_ue - len ( ues ) } " ></td> """ )
2020-09-26 16:19:37 +02:00
# indique le semestre compensé par celui ci:
if decision_sem and decision_sem [ " compense_formsemestre_id " ] :
csem = sco_formsemestre . get_formsemestre (
2021-08-19 10:28:35 +02:00
decision_sem [ " compense_formsemestre_id " ]
2020-09-26 16:19:37 +02:00
)
2022-11-27 19:07:42 +01:00
H . append ( f """ <td><em>compense S { csem [ " semestre_id " ] } </em></td> """ )
2020-09-26 16:19:37 +02:00
else :
H . append ( " <td></td> " )
if with_links :
H . append ( " <td></td> " )
H . append ( " </tr> " )
# 2eme ligne: notes
2022-11-27 19:07:42 +01:00
H . append ( f """ <tr class= " { class_sem } rcp_l2 sem_ { sem [ " formsemestre_id " ] } " > """ )
2020-09-26 16:19:37 +02:00
H . append (
2022-11-27 19:07:42 +01:00
f """ <td class= " rcp_type_sem "
style = " background-color: {bgcolor} ; " > & nbsp ; < / td > """
2020-09-26 16:19:37 +02:00
)
if is_prev :
default_sem_info = ' <span class= " fontred " >[sem. précédent]</span> '
else :
default_sem_info = " "
2021-08-10 12:57:38 +02:00
if not sem [ " etat " ] : # locked
2021-02-04 20:02:44 +01:00
lockicon = scu . icontag ( " lock32_img " , title = " verrouillé " , border = " 0 " )
2020-09-26 16:19:37 +02:00
default_sem_info + = lockicon
2022-02-10 12:13:24 +01:00
if sem [ " formation_code " ] != Se . formation . formation_code :
2022-11-27 19:07:42 +01:00
default_sem_info + = f """ Autre formation: { sem [ " formation_code " ] } """
2020-09-26 16:19:37 +02:00
H . append (
' <td class= " datefin " > %s </td><td class= " sem_info " > %s </td> '
% ( sem [ " mois_fin " ] , sem_info . get ( sem [ " formsemestre_id " ] , default_sem_info ) )
)
# Moy Gen (sous le code decision)
H . append (
2022-11-27 19:07:42 +01:00
f """ <td class= " rcp_moy " > { scu . fmt_note ( nt . get_etud_moy_gen ( etudid ) ) } </td> """
2020-09-26 16:19:37 +02:00
)
# Absences (nb d'abs non just. dans ce semestre)
2023-05-30 15:11:09 +02:00
nbabs , nbabsjust = sco_abs . get_assiduites_count ( etudid , sem )
2022-11-27 19:07:42 +01:00
H . append ( f """ <td class= " rcp_abs " > { nbabs - nbabsjust } </td> """ )
2020-09-26 16:19:37 +02:00
# UEs
for ue in ues :
2022-11-27 19:07:42 +01:00
if decisions_ue and ue . id in decisions_ue :
code = decisions_ue [ ue . id ] [ " code " ]
2020-09-26 16:19:37 +02:00
else :
code = " "
2022-11-27 19:07:42 +01:00
ue_status = etud_ue_status [ ue . id ]
2022-02-12 22:57:46 +01:00
moy_ue = ue_status [ " moy " ] if ue_status else " "
2020-09-26 16:19:37 +02:00
explanation_ue = [ ] # list of strings
if code == ADM :
class_ue = " ue_adm "
elif code == CMP :
class_ue = " ue_cmp "
else :
class_ue = " ue "
2022-02-12 22:57:46 +01:00
if ue_status and ue_status [ " is_external " ] : # validation externe
2020-09-26 16:19:37 +02:00
explanation_ue . append ( " UE externe. " )
2022-07-19 10:28:22 +02:00
2022-02-12 22:57:46 +01:00
if ue_status and ue_status [ " is_capitalized " ] :
2020-09-26 16:19:37 +02:00
class_ue + = " ue_capitalized "
explanation_ue . append (
2022-11-27 19:07:42 +01:00
f """ Capitalisée le { ue_status [ " event_date " ] or " ? " } . """
2020-09-26 16:19:37 +02:00
)
H . append (
2022-11-27 19:07:42 +01:00
f """ <td class= " { class_ue } " title= " {
" " . join ( explanation_ue )
} " > { scu.fmt_note(moy_ue)}</td> " " "
2020-09-26 16:19:37 +02:00
)
if len ( ues ) < Se . nb_max_ue :
2022-11-27 19:07:42 +01:00
H . append ( f """ <td colspan= " { Se . nb_max_ue - len ( ues ) } " ></td> """ )
2020-09-26 16:19:37 +02:00
H . append ( " <td></td> " )
if with_links :
H . append (
2021-05-11 11:48:32 +02:00
' <td><a href= " %s formsemestre_validation_etud_form?formsemestre_id= %s &etudid= %s " >modifier</a></td> '
2020-09-26 16:19:37 +02:00
% ( a_url , sem [ " formsemestre_id " ] , etudid )
)
H . append ( " </tr> " )
# 3eme ligne: ECTS
if (
2021-07-28 17:03:54 +02:00
sco_preferences . get_preference ( " bul_show_ects " , sem [ " formsemestre_id " ] )
2020-09-26 16:19:37 +02:00
or nt . parcours . ECTS_ONLY
) :
2022-07-19 10:28:22 +02:00
etud_ects_infos = nt . get_etud_ects_pot ( etudid ) # ECTS potentiels
2020-09-26 16:19:37 +02:00
H . append (
2022-07-19 10:28:22 +02:00
f """ <tr class= " { class_sem } rcp_l2 sem_ { sem [ " formsemestre_id " ] } " >
< td class = " rcp_type_sem " style = " background-color: {bgcolor} ; " > & nbsp ; < / td >
< td > < / td > """
2020-09-26 16:19:37 +02:00
)
2022-07-19 10:28:22 +02:00
# Total ECTS (affiché sous la moyenne générale)
2020-09-26 16:19:37 +02:00
H . append (
2022-07-19 10:28:22 +02:00
f """ <td class= " sem_ects_tit " ><a title= " crédit acquis " >ECTS:</a></td>
< td class = " sem_ects " > { pv . get ( " sum_ects " , 0 ) : 2.2 g } / { etud_ects_infos [ " ects_total " ] : 2.2 g } < / td >
< td class = " rcp_abs " > < / td >
"""
2020-09-26 16:19:37 +02:00
)
# ECTS validables dans chaque UE
for ue in ues :
2022-11-27 19:07:42 +01:00
ue_status = nt . get_etud_ue_status ( etudid , ue . id )
2022-07-19 10:28:22 +02:00
if ue_status :
ects = ue_status [ " ects " ]
ects_pot = ue_status [ " ects_pot " ]
H . append (
2022-11-27 19:07:42 +01:00
f """ <td class= " ue "
title = " {ects:2.2g} / {ects_pot:2.2g} ECTS " > { ects : 2.2 g } < / td > """
2022-07-19 10:28:22 +02:00
)
else :
2022-11-27 19:07:42 +01:00
H . append ( """ <td class= " ue " ></td> """ )
2020-09-26 16:19:37 +02:00
H . append ( " <td></td></tr> " )
H . append ( " </table> " )
return " \n " . join ( H )
2021-08-21 00:24:51 +02:00
def form_decision_manuelle ( Se , formsemestre_id , etudid , desturl = " " , sortcol = None ) :
2021-01-01 18:40:47 +01:00
""" Formulaire pour saisie décision manuelle """
2020-09-26 16:19:37 +02:00
H = [
"""
< script type = " text/javascript " >
function IsEmpty ( aTextField ) {
if ( ( aTextField . value . length == 0 ) | | ( aTextField . value == null ) ) {
return true ;
} else { return false ; }
}
function check_sfv_form ( ) {
if ( IsEmpty ( document . forms . formvalidmanu . code_etat ) ) {
alert ( ' Choisir un code semestre ! ' ) ;
return false ;
}
return true ;
}
< / script >
< form method = " get " action = " formsemestre_validation_etud_manu " name = " formvalidmanu " id = " formvalidmanu " class = " sfv_decisions sfv_decisions_manuelles " onsubmit = " return check_sfv_form() " >
< input type = " hidden " name = " etudid " value = " %s " / >
< input type = " hidden " name = " formsemestre_id " value = " %s " / >
"""
% ( etudid , formsemestre_id )
]
if desturl :
H . append ( ' <input type= " hidden " name= " desturl " value= " %s " /> ' % desturl )
if sortcol :
H . append ( ' <input type= " hidden " name= " sortcol " value= " %s " /> ' % sortcol )
H . append (
' <h3 class= " sfv " >Décisions manuelles : <em>(vérifiez bien votre choix !)</em></h3><table> '
)
# Choix code semestre:
2023-02-12 13:36:47 +01:00
codes = sorted ( codes_cursus . CODES_JURY_SEM )
2023-01-23 11:38:47 +01:00
# fortuitement, cet ordre convient bien !
2020-09-26 16:19:37 +02:00
H . append (
' <tr><td>Code semestre: </td><td><select name= " code_etat " ><option value= " " selected>Choisir...</option> '
)
for cod in codes :
if cod in Se . parcours . UNUSED_CODES :
continue
if cod != ADC :
H . append (
' <option value= " %s " > %s (code %s )</option> '
2023-02-12 13:36:47 +01:00
% ( cod , codes_cursus . CODES_EXPL [ cod ] , cod )
2020-09-26 16:19:37 +02:00
)
2021-08-11 00:36:07 +02:00
elif Se . sem [ " gestion_compensation " ] :
2020-09-26 16:19:37 +02:00
# traitement spécial pour ADC (compensation)
# ne propose que les semestres avec lesquels on peut compenser
# le code transmis est ADC_formsemestre_id
# on propose aussi une compensation sans utiliser de semestre, pour les cas ou le semestre
# précédent n'est pas géré dans ScoDoc (code ADC_)
# log(str(Se.sems))
for sem in Se . sems :
if sem [ " can_compensate " ] :
H . append (
' <option value= " %s _ %s " >Admis par compensation avec S %s ( %s )</option> '
% (
cod ,
sem [ " formsemestre_id " ] ,
sem [ " semestre_id " ] ,
sem [ " date_debut " ] ,
)
)
if Se . could_be_compensated ( ) :
H . append (
' <option value= " ADC_ " >Admis par compensation (avec un semestre hors ScoDoc)</option> '
)
H . append ( " </select></td></tr> " )
# Choix code semestre precedent:
if Se . prev :
H . append (
' <tr><td>Code semestre précédent: </td><td><select name= " new_code_prev " ><option value= " " >Choisir une décision...</option> '
)
for cod in codes :
if cod == ADC : # ne propose pas ce choix
continue
if Se . prev_decision and cod == Se . prev_decision [ " code " ] :
sel = " selected "
else :
sel = " "
H . append (
' <option value= " %s " %s > %s (code %s )</option> '
2023-02-12 13:36:47 +01:00
% ( cod , sel , codes_cursus . CODES_EXPL [ cod ] , cod )
2020-09-26 16:19:37 +02:00
)
H . append ( " </select></td></tr> " )
# Choix code devenir
2023-02-12 13:36:47 +01:00
codes = list ( codes_cursus . DEVENIR_EXPL . keys ( ) )
2020-09-26 16:19:37 +02:00
codes . sort ( ) # fortuitement, cet ordre convient aussi bien !
if Se . sem [ " semestre_id " ] == - 1 :
2023-02-12 13:36:47 +01:00
allowed_codes = codes_cursus . DEVENIRS_MONO
2020-09-26 16:19:37 +02:00
else :
2023-02-12 13:36:47 +01:00
allowed_codes = set ( codes_cursus . DEVENIRS_STD )
2020-09-26 16:19:37 +02:00
# semestres decales ?
2021-08-11 00:36:07 +02:00
if Se . sem [ " gestion_semestrielle " ] :
2023-02-12 13:36:47 +01:00
allowed_codes = allowed_codes . union ( codes_cursus . DEVENIRS_DEC )
2020-09-26 16:19:37 +02:00
# n'autorise les codes NEXT2 que si semestres décalés et s'il ne manque qu'un semestre avant le n+2
if Se . can_jump_to_next2 ( ) :
2023-02-12 13:36:47 +01:00
allowed_codes = allowed_codes . union ( codes_cursus . DEVENIRS_NEXT2 )
2020-09-26 16:19:37 +02:00
H . append (
' <tr><td>Devenir: </td><td><select name= " devenir " ><option value= " " selected>Choisir...</option> '
)
for cod in codes :
if cod in allowed_codes : # or Se.sem['gestion_semestrielle'] == '1'
H . append ( ' <option value= " %s " > %s </option> ' % ( cod , Se . explique_devenir ( cod ) ) )
H . append ( " </select></td></tr> " )
H . append (
' <tr><td><input type= " checkbox " name= " assidu " checked= " checked " >assidu</input></td></tr> '
)
H . append (
""" </table>
< input type = " submit " name = " formvalidmanu_submit " value = " Valider décision manuelle " / >
2021-05-11 11:48:32 +02:00
< span style = " padding-left: 5em; " > < a href = " formsemestre_validation_suppress_etud?etudid= %s &formsemestre_id= %s " class = " stdlink " > Supprimer décision existante < / a > < / span >
2020-09-26 16:19:37 +02:00
< / form >
"""
% ( etudid , formsemestre_id )
)
return " \n " . join ( H )
# -----------
2021-09-27 10:20:10 +02:00
def formsemestre_validation_auto ( formsemestre_id ) :
2020-09-26 16:19:37 +02:00
" Formulaire saisie automatisee des decisions d ' un semestre "
H = [
2022-01-07 15:11:24 +01:00
html_sco_header . html_sem_header ( " Saisie automatique des décisions du semestre " ) ,
2022-07-11 18:28:58 +02:00
f """
2020-09-26 16:19:37 +02:00
< ul >
< li > Seuls les étudiants qui obtiennent le semestre seront affectés ( code ADM , moyenne générale et
toutes les barres , semestre précédent validé ) ; < / li >
< li > le semestre précédent , s ' il y en a un, doit avoir été validé;</li>
< li > les décisions du semestre précédent ne seront pas modifiées ; < / li >
< li > l ' assiduité n ' est < b > pas < / b > prise en compte ; < / li >
< li > les étudiants avec des notes en attente sont ignorés . < / li >
< / ul >
< p > Il est donc vivement conseillé de relire soigneusement les décisions à l ' issue
de cette procédure ! < / p >
< form action = " do_formsemestre_validation_auto " >
2022-07-11 18:28:58 +02:00
< input type = " hidden " name = " formsemestre_id " value = " {formsemestre_id} " / >
2020-09-26 16:19:37 +02:00
< input type = " submit " value = " Calculer automatiquement ces décisions " / >
< p > < em > Le calcul prend quelques minutes , soyez patients ! < / em > < / p >
< / form >
2022-07-11 18:28:58 +02:00
""" ,
2021-07-29 10:19:00 +02:00
html_sco_header . sco_footer ( ) ,
2020-09-26 16:19:37 +02:00
]
return " \n " . join ( H )
2021-09-27 10:20:10 +02:00
def do_formsemestre_validation_auto ( formsemestre_id ) :
2020-09-26 16:19:37 +02:00
" Saisie automatisee des decisions d ' un semestre "
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
next_semestre_id = sem [ " semestre_id " ] + 1
2023-03-20 11:17:38 +01:00
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
2022-02-12 22:57:46 +01:00
nt : NotesTableCompat = res_sem . load_formsemestre_results ( formsemestre )
2020-09-26 16:19:37 +02:00
etudids = nt . get_etudids ( )
nb_valid = 0
conflicts = [ ] # liste des etudiants avec decision differente déjà saisie
2022-07-11 18:28:58 +02:00
with sco_cache . DeferredSemCacheManager ( ) :
for etudid in etudids :
etud = sco_etud . get_etud_info ( etudid = etudid , filled = True ) [ 0 ]
Se = sco_cursus . get_situation_etud_cursus ( etud , formsemestre_id )
ins = sco_formsemestre_inscriptions . do_formsemestre_inscription_list (
{ " etudid " : etudid , " formsemestre_id " : formsemestre_id }
) [ 0 ]
# Conditions pour validation automatique:
2022-09-30 22:43:39 +02:00
if ins [ " etat " ] == scu . INSCRIT and (
2022-07-11 18:28:58 +02:00
(
( not Se . prev )
or (
Se . prev_decision and Se . prev_decision [ " code " ] in ( ADM , ADC , ADJ )
)
2020-09-26 16:19:37 +02:00
)
2022-07-11 18:28:58 +02:00
and Se . barre_moy_ok
and Se . barres_ue_ok
and not etud_has_notes_attente ( etudid , formsemestre_id )
) :
# check: s'il existe une decision ou autorisation et qu'elles sont differentes,
# warning (et ne fait rien)
decision_sem = nt . get_etud_decision_sem ( etudid )
ok = True
if decision_sem and decision_sem [ " code " ] != ADM :
ok = False
conflicts . append ( etud )
autorisations = ScolarAutorisationInscription . query . filter_by (
etudid = etudid , origin_formsemestre_id = formsemestre_id
) . all ( )
if len ( autorisations ) != 0 :
if (
len ( autorisations ) > 1
or autorisations [ 0 ] . semestre_id != next_semestre_id
) :
if ok :
conflicts . append ( etud )
ok = False
# ok, valide !
if ok :
formsemestre_validation_etud_manu (
formsemestre_id ,
etudid ,
code_etat = ADM ,
devenir = " NEXT " ,
assidu = True ,
redirect = False ,
)
nb_valid + = 1
2020-09-26 16:19:37 +02:00
log (
2023-06-23 10:37:32 +02:00
f " do_formsemestre_validation_auto: { nb_valid } validations, { len ( conflicts ) } conflicts "
2020-09-26 16:19:37 +02:00
)
2023-06-23 10:37:32 +02:00
ScolarNews . add (
typ = ScolarNews . NEWS_JURY ,
obj = formsemestre . id ,
text = f """ Calcul jury automatique du semestre { formsemestre . html_link_status ( )
} ( { nb_valid } décisions ) """ ,
url = url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre . id ,
) ,
2020-09-26 16:19:37 +02:00
)
2023-06-23 10:37:32 +02:00
H = [
f """ { html_sco_header . sco_header ( page_title = " Saisie automatique " ) }
< h2 > Saisie automatique des décisions du semestre { formsemestre . titre_annee ( ) } < / h2 >
< p > Opération effectuée . < / p >
< p > { nb_valid } étudiants validés sur { len ( etudids ) } < / p >
"""
]
2020-09-26 16:19:37 +02:00
if conflicts :
H . append (
2022-04-07 23:31:08 +02:00
f """ <p><b>Attention:</b> { len ( conflicts ) } étudiants non modifiés
car décisions différentes déja saisies :
< ul > """
2020-09-26 16:19:37 +02:00
)
for etud in conflicts :
H . append (
2022-04-07 23:31:08 +02:00
f """ <li><a href= " {
url_for ( ' notes.formsemestre_validation_etud_form ' ,
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre_id ,
etudid = etud [ " etudid " ] , check = 1 )
} " > {etud["nomprenom"]} </li> " " "
2020-09-26 16:19:37 +02:00
)
H . append ( " </ul> " )
H . append (
2022-04-07 23:31:08 +02:00
f """ <a href= " { url_for ( ' notes.formsemestre_recapcomplet ' ,
2022-06-29 16:30:01 +02:00
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre_id , mode_jury = 1 )
2022-04-07 23:31:08 +02:00
} " >continuer</a> " " "
2020-09-26 16:19:37 +02:00
)
2021-07-29 10:19:00 +02:00
H . append ( html_sco_header . sco_footer ( ) )
2020-09-26 16:19:37 +02:00
return " \n " . join ( H )
2021-08-21 00:24:51 +02:00
def formsemestre_validation_suppress_etud ( formsemestre_id , etudid ) :
2022-07-06 00:05:14 +02:00
""" Suppression des décisions de jury pour un étudiant/formsemestre.
Efface toutes les décisions enregistrées concernant ce formsemestre et cet étudiant :
code semestre , UEs , autorisations d ' inscription
"""
log ( f " formsemestre_validation_suppress_etud( { formsemestre_id } , { etudid } ) " )
# Validations jury classiques (semestres, UEs, autorisations)
for v in ScolarFormSemestreValidation . query . filter_by (
etudid = etudid , formsemestre_id = formsemestre_id
) :
db . session . delete ( v )
for v in ScolarAutorisationInscription . query . filter_by (
etudid = etudid , origin_formsemestre_id = formsemestre_id
) :
db . session . delete ( v )
# Validations jury spécifiques BUT
for v in ApcValidationRCUE . query . filter_by (
etudid = etudid , formsemestre_id = formsemestre_id
) :
db . session . delete ( v )
for v in ApcValidationAnnee . query . filter_by (
etudid = etudid , formsemestre_id = formsemestre_id
) :
db . session . delete ( v )
db . session . commit ( )
2020-09-26 16:19:37 +02:00
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
_invalidate_etud_formation_caches (
2021-08-21 00:24:51 +02:00
etudid , sem [ " formation_id " ]
2020-09-26 16:19:37 +02:00
) # > suppr. decision jury (peut affecter de plusieurs semestres utilisant UE capitalisée)
2021-09-27 10:20:10 +02:00
def formsemestre_validate_previous_ue ( formsemestre_id , etudid ) :
2021-01-01 18:40:47 +01:00
""" Form. saisie UE validée hors ScoDoc
2020-09-26 16:19:37 +02:00
( pour étudiants arrivant avec un UE antérieurement validée ) .
"""
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
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2023-02-18 00:13:00 +01:00
formation : Formation = Formation . query . get_or_404 ( sem [ " formation_id " ] )
2020-09-26 16:19:37 +02:00
H = [
2021-06-13 23:37:14 +02:00
html_sco_header . sco_header (
2020-09-26 16:19:37 +02:00
page_title = " Validation UE " ,
javascripts = [ " js/validate_previous_ue.js " ] ,
) ,
' <table style= " width: 100 % " ><tr><td> ' ,
""" <h2 class= " formsemestre " > %s : validation d ' une UE antérieure</h2> """
% etud [ " nomprenom " ] ,
(
2021-07-11 17:37:12 +02:00
' </td><td style= " text-align: right; " ><a href= " %s " > %s </a></td></tr></table> '
2020-09-26 16:19:37 +02:00
% (
2021-07-11 17:37:12 +02:00
url_for ( " scolar.ficheEtud " , scodoc_dept = g . scodoc_dept , etudid = etudid ) ,
2021-09-24 12:10:53 +02:00
sco_photos . etud_photo_html ( etud , title = " fiche de %s " % etud [ " nom " ] ) ,
2020-09-26 16:19:37 +02:00
)
) ,
2023-02-18 00:13:00 +01:00
f """ <p class= " help " >Utiliser cette page pour enregistrer une UE validée antérieurement,
2020-09-26 16:19:37 +02:00
< em > dans un semestre hors ScoDoc < / em > . < / p >
< p > < b > Les UE validées dans ScoDoc sont déjà
2023-02-18 00:13:00 +01:00
automatiquement prises en compte < / b > . Cette page n ' est utile que pour les étudiants ayant
2023-06-15 08:49:05 +02:00
suivi un début de cursus dans < b > un autre établissement < / b > , ou bien dans un semestre géré
< b > sans ScoDoc < / b > et qui < b > redouble < / b > ce semestre
2023-02-18 00:13:00 +01:00
( < em > ne pas utiliser pour les semestres précédents ! < / em > ) .
2020-09-26 16:19:37 +02:00
< / p >
2023-02-18 00:13:00 +01:00
< p > Notez que l ' UE est validée, avec enregistrement immédiat de la décision et
l ' attribution des ECTS.</p>
< p > On ne peut prendre en compte ici que les UE du cursus < b > { formation . titre } < / b > < / p >
""" ,
2020-09-26 16:19:37 +02:00
]
# Toutes les UE de cette formation sont présentées (même celles des autres semestres)
2023-02-18 00:13:00 +01:00
ues = formation . ues . order_by ( UniteEns . numero )
ue_names = [ " Choisir... " ] + [ f " { ue . acronyme } { ue . titre } " for ue in ues ]
ue_ids = [ " " ] + [ ue . id for ue in ues ]
2020-09-26 16:19:37 +02:00
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
(
( " etudid " , { " input_type " : " hidden " } ) ,
( " formsemestre_id " , { " input_type " : " hidden " } ) ,
(
" ue_id " ,
{
" input_type " : " menu " ,
" title " : " Unité d ' Enseignement (UE) " ,
" allow_null " : False ,
" allowed_values " : ue_ids ,
" labels " : ue_names ,
} ,
) ,
(
" semestre_id " ,
{
" input_type " : " menu " ,
" title " : " Indice du semestre " ,
" explanation " : " Facultatif: indice du semestre dans la formation " ,
" allow_null " : True ,
2022-02-06 16:09:17 +01:00
" allowed_values " : [ " " ] + [ x for x in range ( 11 ) ] ,
2021-07-09 17:47:06 +02:00
" labels " : [ " - " ] + list ( range ( 11 ) ) ,
2020-09-26 16:19:37 +02:00
} ,
) ,
(
" date " ,
{
" input_type " : " date " ,
" size " : 9 ,
" explanation " : " j/m/a " ,
" default " : time . strftime ( " %d / % m/ % Y " ) ,
} ,
) ,
(
" moy_ue " ,
{
" type " : " float " ,
" allow_null " : False ,
" min_value " : 0 ,
" max_value " : 20 ,
" title " : " Moyenne (/20) obtenue dans cette UE: " ,
} ,
) ,
) ,
cancelbutton = " Annuler " ,
submitlabel = " Enregistrer validation d ' UE " ,
)
if tf [ 0 ] == 0 :
X = """
< div id = " ue_list_etud_validations " > < ! - - filled by get_etud_ue_cap_html - - > < / div >
< div id = " ue_list_code " > < ! - - filled by ue_sharing_code - - > < / div >
"""
2023-02-18 00:13:00 +01:00
warn , ue_multiples = check_formation_ues ( formation . id )
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + tf [ 1 ] + X + warn + html_sco_header . sco_footer ( )
2020-09-26 16:19:37 +02:00
elif tf [ 0 ] == - 1 :
2021-07-31 18:01:10 +02:00
return flask . redirect (
2021-08-11 00:36:07 +02:00
scu . NotesURL ( )
+ " /formsemestre_status?formsemestre_id= "
+ str ( formsemestre_id )
2020-09-26 16:19:37 +02:00
)
else :
if tf [ 2 ] [ " semestre_id " ] :
semestre_id = int ( tf [ 2 ] [ " semestre_id " ] )
else :
semestre_id = None
do_formsemestre_validate_previous_ue (
formsemestre_id ,
etudid ,
tf [ 2 ] [ " ue_id " ] ,
tf [ 2 ] [ " moy_ue " ] ,
tf [ 2 ] [ " date " ] ,
semestre_id = semestre_id ,
)
2023-02-18 00:13:00 +01:00
flash ( " Validation d ' UE enregistrée " )
2021-07-31 18:01:10 +02:00
return flask . redirect (
2023-02-18 00:13:00 +01:00
url_for (
" notes.formsemestre_bulletinetud " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre_id ,
etudid = etudid ,
)
2020-09-26 16:19:37 +02:00
)
def do_formsemestre_validate_previous_ue (
formsemestre_id ,
etudid ,
ue_id ,
moy_ue ,
date ,
code = ADM ,
semestre_id = None ,
ue_coefficient = None ,
) :
""" Enregistre (ou modifie) validation d ' UE (obtenue hors ScoDoc).
2021-01-01 18:40:47 +01:00
Si le coefficient est spécifié , modifie le coefficient de
2020-09-26 16:19:37 +02:00
cette UE ( utile seulement pour les semestres extérieurs ) .
"""
2023-03-20 11:17:38 +01:00
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
2022-02-12 22:57:46 +01:00
nt : NotesTableCompat = res_sem . load_formsemestre_results ( formsemestre )
2022-12-25 01:35:18 +01:00
ue : UniteEns = UniteEns . query . get_or_404 ( ue_id )
2022-02-12 22:57:46 +01:00
2021-11-12 22:17:46 +01:00
cnx = ndb . GetDBConnexion ( )
2020-09-26 16:19:37 +02:00
if ue_coefficient != None :
2021-01-17 22:31:28 +01:00
sco_formsemestre . do_formsemestre_uecoef_edit_or_create (
2021-08-19 10:28:35 +02:00
cnx , formsemestre_id , ue_id , ue_coefficient
2020-09-26 16:19:37 +02:00
)
else :
2021-08-19 10:28:35 +02:00
sco_formsemestre . do_formsemestre_uecoef_delete ( cnx , formsemestre_id , ue_id )
2022-07-07 16:24:52 +02:00
sco_cursus_dut . do_formsemestre_validate_ue (
2020-09-26 16:19:37 +02:00
cnx ,
nt ,
formsemestre_id , # "importe" cette UE dans le semestre (new 3/2015)
etudid ,
ue_id ,
code ,
moy_ue = moy_ue ,
date = date ,
semestre_id = semestre_id ,
2021-08-11 00:36:07 +02:00
is_external = True ,
2020-09-26 16:19:37 +02:00
)
logdb (
cnx ,
method = " formsemestre_validate_previous_ue " ,
etudid = etudid ,
2022-12-25 01:35:18 +01:00
msg = f " Validation UE prec. { ue_id } { ue . acronyme } : { code } " ,
2020-09-26 16:19:37 +02:00
commit = False ,
)
2022-12-25 01:35:18 +01:00
_invalidate_etud_formation_caches ( etudid , formsemestre . formation_id )
2020-09-26 16:19:37 +02:00
cnx . commit ( )
2021-08-21 00:24:51 +02:00
def _invalidate_etud_formation_caches ( etudid , formation_id ) :
2020-09-26 16:19:37 +02:00
" Invalide tous les semestres de cette formation où l ' etudiant est inscrit... "
2021-02-03 22:00:41 +01:00
r = ndb . SimpleDictFetch (
2021-08-08 17:38:46 +02:00
""" SELECT sem.id
2020-09-26 16:19:37 +02:00
FROM notes_formsemestre sem , notes_formsemestre_inscription i
WHERE sem . formation_id = % ( formation_id ) s
2021-08-08 17:38:46 +02:00
AND i . formsemestre_id = sem . id
2020-09-26 16:19:37 +02:00
AND i . etudid = % ( etudid ) s
""" ,
{ " etudid " : etudid , " formation_id " : formation_id } ,
)
2021-08-08 17:38:46 +02:00
for fsid in [ s [ " id " ] for s in r ] :
2021-07-19 19:53:01 +02:00
sco_cache . invalidate_formsemestre (
formsemestre_id = fsid
2020-09-26 16:19:37 +02:00
) # > modif decision UE (inval tous semestres avec cet etudiant, ok mais conservatif)
2021-09-27 10:20:10 +02:00
def get_etud_ue_cap_html ( etudid , formsemestre_id , ue_id ) :
2021-01-01 18:40:47 +01:00
""" Ramene bout de HTML pour pouvoir supprimer une validation de cette UE """
2021-02-03 22:00:41 +01:00
valids = ndb . SimpleDictFetch (
2021-08-08 17:38:46 +02:00
""" SELECT SFV.*
FROM scolar_formsemestre_validation SFV
WHERE ue_id = % ( ue_id ) s
AND etudid = % ( etudid ) s """ ,
2020-09-26 16:19:37 +02:00
{ " etudid " : etudid , " ue_id " : ue_id } ,
)
if not valids :
return " "
H = [
' <div class= " existing_valids " ><span>Validations existantes pour cette UE:</span><ul> '
]
for valid in valids :
2021-02-03 22:00:41 +01:00
valid [ " event_date " ] = ndb . DateISOtoDMY ( valid [ " event_date " ] )
2020-09-26 16:19:37 +02:00
if valid [ " moy_ue " ] != None :
valid [ " m " ] = " , moyenne %(moy_ue)g /20 " % valid
else :
valid [ " m " ] = " "
if valid [ " formsemestre_id " ] :
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( valid [ " formsemestre_id " ] )
2020-09-26 16:19:37 +02:00
valid [ " s " ] = " , du semestre %s " % sem [ " titreannee " ]
else :
valid [ " s " ] = " enregistrée d ' un parcours antérieur (hors ScoDoc) "
if valid [ " semestre_id " ] :
valid [ " s " ] + = " (<b>S %d </b>) " % valid [ " semestre_id " ]
valid [ " ds " ] = formsemestre_id
H . append (
2021-05-11 11:48:32 +02:00
' <li> %(code)s %(m)s %(s)s , le %(event_date)s <a class= " stdlink " href= " etud_ue_suppress_validation?etudid= %(etudid)s &ue_id= %(ue_id)s &formsemestre_id= %(ds)s " title= " supprime cette validation " >effacer</a></li> '
2020-09-26 16:19:37 +02:00
% valid
)
H . append ( " </ul></div> " )
return " \n " . join ( H )
2021-09-27 10:20:10 +02:00
def etud_ue_suppress_validation ( etudid , formsemestre_id , ue_id ) :
2020-09-26 16:19:37 +02:00
""" Suppress a validation (ue_id, etudid) and redirect to formsemestre """
log ( " etud_ue_suppress_validation( %s , %s , %s ) " % ( etudid , formsemestre_id , ue_id ) )
2021-06-15 13:59:56 +02:00
cnx = ndb . GetDBConnexion ( )
2021-02-03 22:00:41 +01:00
cursor = cnx . cursor ( cursor_factory = ndb . ScoDocCursor )
2020-09-26 16:19:37 +02:00
cursor . execute (
" DELETE FROM scolar_formsemestre_validation WHERE etudid= %(etudid)s and ue_id= %(ue_id)s " ,
{ " etudid " : etudid , " ue_id " : ue_id } ,
)
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2021-08-21 00:24:51 +02:00
_invalidate_etud_formation_caches ( etudid , sem [ " formation_id " ] )
2020-09-26 16:19:37 +02:00
2021-07-31 18:01:10 +02:00
return flask . redirect (
2021-06-15 12:34:33 +02:00
scu . NotesURL ( )
2021-05-11 11:48:32 +02:00
+ " /formsemestre_validate_previous_ue?etudid= %s &formsemestre_id= %s "
2020-09-26 16:19:37 +02:00
% ( etudid , formsemestre_id )
)
2021-08-20 01:09:55 +02:00
def check_formation_ues ( formation_id ) :
2020-09-26 16:19:37 +02:00
""" Verifie que les UE d ' une formation sont chacune utilisée dans un seul semestre_id
Si ce n ' est pas le cas, c ' est probablement ( mais pas forcément ) une erreur de
définition du programme : cette fonction retourne un bout de HTML
à afficher pour prévenir l ' utilisateur, ou ' ' si tout est ok.
"""
2021-10-17 23:19:26 +02:00
ues = sco_edit_ue . ue_list ( { " formation_id " : formation_id } )
2020-09-26 16:19:37 +02:00
ue_multiples = { } # { ue_id : [ liste des formsemestre ] }
for ue in ues :
# formsemestres utilisant cette ue ?
2021-02-03 22:00:41 +01:00
sems = ndb . SimpleDictFetch (
2022-02-19 16:16:52 +01:00
""" SELECT DISTINCT sem.id AS formsemestre_id, sem.*
2020-09-26 16:19:37 +02:00
FROM notes_formsemestre sem , notes_modules mod , notes_moduleimpl mi
WHERE sem . formation_id = % ( formation_id ) s
2021-08-08 17:38:46 +02:00
AND mod . id = mi . module_id
AND mi . formsemestre_id = sem . id
AND mod . ue_id = % ( ue_id ) s
""" ,
2020-09-26 16:19:37 +02:00
{ " ue_id " : ue [ " ue_id " ] , " formation_id " : formation_id } ,
)
semestre_ids = set ( [ x [ " semestre_id " ] for x in sems ] )
if (
len ( semestre_ids ) > 1
) : # plusieurs semestres d'indices differents dans le cursus
ue_multiples [ ue [ " ue_id " ] ] = sems
if not ue_multiples :
return " " , { }
# Genere message HTML:
H = [
2022-02-19 16:16:52 +01:00
""" <div class= " ue_warning " ><span>Attention:</span> les UE suivantes de cette formation
2020-09-26 16:19:37 +02:00
sont utilisées dans des
2022-10-02 23:43:29 +02:00
semestres de rangs différents ( eg S1 et S3 ) . < br > Cela peut engendrer des problèmes pour
2022-02-19 16:16:52 +01:00
la capitalisation des UE . Il serait préférable d ' essayer de rectifier cette situation:
soit modifier le programme de la formation ( définir des UE dans chaque semestre ) ,
2020-09-26 16:19:37 +02:00
soit veiller à saisir le bon indice de semestre dans le menu lors de la validation d ' une
UE extérieure .
< ul >
"""
]
for ue in ues :
if ue [ " ue_id " ] in ue_multiples :
sems = [
2021-08-19 10:28:35 +02:00
sco_formsemestre . get_formsemestre ( x [ " formsemestre_id " ] )
2020-09-26 16:19:37 +02:00
for x in ue_multiples [ ue [ " ue_id " ] ]
]
slist = " , " . join (
2022-02-19 16:16:52 +01:00
[
""" %(titreannee)s (<em>semestre <b class= " fontred " > %(semestre_id)s </b></em>) """
% s
for s in sems
]
2020-09-26 16:19:37 +02:00
)
H . append ( " <li><b> %s </b> : %s </li> " % ( ue [ " acronyme " ] , slist ) )
H . append ( " </ul></div> " )
return " \n " . join ( H ) , ue_multiples