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
#
##############################################################################
""" Form choix modules / responsables et creation formsemestre
"""
2021-08-01 10:16:16 +02:00
import flask
2023-01-14 00:05:39 +01:00
from flask import url_for , flash , redirect
2022-01-30 08:13:24 +01:00
from flask import g , request
2021-08-11 00:36:07 +02:00
from flask_login import current_user
2020-09-26 16:19:37 +02:00
2021-12-12 16:24:50 +01:00
from app import db
from app . auth . models import User
2021-12-29 19:30:49 +01:00
from app . models import APO_CODE_STR_LEN , SHORT_STR_LEN
2023-02-27 17:45:20 +01:00
from app . models import (
Module ,
ModuleImpl ,
Evaluation ,
UniteEns ,
ScolarFormSemestreValidation ,
ScolarAutorisationInscription ,
ApcValidationAnnee ,
ApcValidationRCUE ,
ScolarNews ,
)
2022-01-30 08:13:24 +01:00
from app . models . formations import Formation
from app . models . formsemestre import FormSemestre
2022-05-22 03:26:39 +02:00
from app . models . but_refcomp import ApcParcours
2021-06-19 23:21:37 +02:00
import app . scodoc . notesdb as ndb
import app . scodoc . sco_utils as scu
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_groups
2021-08-29 19:57:32 +02:00
from app import log
2022-05-22 03:26:39 +02:00
from app . scodoc . TrivialFormulator import TrivialFormulator
2021-06-19 23:21:37 +02:00
from app . scodoc . sco_exceptions import AccessDenied , ScoValueError
from app . scodoc . sco_permissions import Permission
2021-07-10 13:55:35 +02:00
from app . scodoc . sco_vdi import ApoEtapeVDI
2021-06-19 23:21:37 +02:00
from app . scodoc import html_sco_header
2023-02-12 13:36:47 +01:00
from app . scodoc import codes_cursus
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_compute_moy
from app . scodoc import sco_edit_module
2023-02-20 21:04:29 +01:00
from app . scodoc import sco_edit_ue
2021-11-12 22:17:46 +01:00
from app . scodoc import sco_evaluation_db
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_formsemestre
2021-10-12 16:05:50 +02:00
from app . scodoc import sco_groups_copy
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_modalites
from app . scodoc import sco_moduleimpl
from app . scodoc import sco_permissions_check
from app . scodoc import sco_portal_apogee
from app . scodoc import sco_preferences
2021-06-26 21:57:54 +02:00
from app . scodoc import sco_users
2020-09-26 16:19:37 +02:00
2022-01-30 08:13:24 +01:00
def _default_sem_title ( formation ) :
""" Default title for a semestre in formation """
return formation . titre
2020-09-26 16:19:37 +02:00
2021-09-27 10:20:10 +02:00
def formsemestre_createwithmodules ( ) :
2020-09-26 16:19:37 +02:00
""" Page création d ' un semestre """
H = [
2021-06-13 18:29:53 +02:00
html_sco_header . sco_header (
2020-09-26 16:19:37 +02:00
page_title = " Création d ' un semestre " ,
2022-02-28 17:57:12 +01:00
javascripts = [ " libjs/AutoSuggest.js " , " js/formsemestre_edit.js " ] ,
2020-09-26 16:19:37 +02:00
cssstyles = [ " css/autosuggest_inquisitor.css " ] ,
bodyOnLoad = " init_tf_form( ' ' ) " ,
) ,
""" <h2>Mise en place d ' un semestre de formation</h2> """ ,
]
2021-09-27 10:20:10 +02:00
r = do_formsemestre_createwithmodules ( )
2021-08-29 19:57:32 +02:00
if isinstance ( r , str ) :
2021-07-05 23:32:57 +02:00
H . append ( r )
else :
return r # response redirect
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + html_sco_header . sco_footer ( )
2020-09-26 16:19:37 +02:00
2021-09-27 10:20:10 +02:00
def formsemestre_editwithmodules ( formsemestre_id ) :
2020-09-26 16:19:37 +02:00
""" Page modification semestre """
2022-10-01 15:34:39 +02:00
formsemestre : FormSemestre = FormSemestre . query . filter_by (
id = formsemestre_id , dept_id = g . scodoc_dept_id
) . first_or_404 ( )
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
" Modification du semestre " ,
2022-02-28 17:57:12 +01:00
javascripts = [ " libjs/AutoSuggest.js " , " js/formsemestre_edit.js " ] ,
2020-09-26 16:19:37 +02:00
cssstyles = [ " css/autosuggest_inquisitor.css " ] ,
bodyOnLoad = " init_tf_form( ' ' ) " ,
)
]
2022-10-01 15:34:39 +02:00
if not formsemestre . etat :
2020-09-26 16:19:37 +02:00
H . append (
2022-08-31 19:14:21 +02:00
f """ <p> { scu . icontag (
" lock_img " , border = " 0 " , title = " Semestre verrouillé " )
} < b > Ce semestre est verrouillé . < / b > < / p > """
2020-09-26 16:19:37 +02:00
)
else :
2022-10-01 15:34:39 +02:00
r = do_formsemestre_createwithmodules ( edit = True , formsemestre = formsemestre )
2021-08-29 19:57:32 +02:00
if isinstance ( r , str ) :
2021-07-05 23:32:57 +02:00
H . append ( r )
else :
return r # response redirect
2021-09-28 09:14:04 +02:00
vals = scu . get_request_args ( )
2021-09-27 10:20:10 +02:00
if not vals . get ( " tf_submitted " , False ) :
2020-09-26 16:19:37 +02:00
H . append (
2022-05-22 03:26:39 +02:00
""" <p class= " help " >Seuls les modules cochés font partie de ce semestre.
2022-02-02 10:49:34 +01:00
Pour les retirer , les décocher et appuyer sur le bouton " modifier " .
< / p >
2022-05-22 03:26:39 +02:00
< p class = " help " > Attention : s ' il y a déjà des évaluations dans un module,
2022-02-02 10:49:34 +01:00
il ne peut pas être supprimé ! < / p >
2022-05-22 03:26:39 +02:00
< p class = " help " > Les modules ont toujours un responsable .
2022-02-02 10:49:34 +01:00
Par défaut , c ' est le directeur des études.</p>
< p class = " help " > Un semestre ne peut comporter qu ' une seule UE " bonus
sport / culture " </p>
"""
2020-09-26 16:19:37 +02:00
)
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + html_sco_header . sco_footer ( )
2020-09-26 16:19:37 +02:00
2022-10-01 15:34:39 +02:00
def can_edit_sem ( formsemestre_id : int = None , sem = None ) :
2020-12-16 01:34:08 +01:00
""" Return sem if user can edit it, False otherwise """
2021-08-19 10:28:35 +02:00
sem = sem or sco_formsemestre . get_formsemestre ( formsemestre_id )
2021-08-11 00:36:07 +02:00
if not current_user . has_permission ( Permission . ScoImplement ) : # pas chef
if not sem [ " resp_can_edit " ] or current_user . id not in sem [ " responsables " ] :
2020-09-26 16:19:37 +02:00
return False
return sem
2022-09-01 16:55:20 +02:00
resp_fields = [
" responsable_id " ,
" responsable_id2 " ,
" responsable_id3 " ,
" responsable_id4 " ,
]
2022-10-01 15:34:39 +02:00
def do_formsemestre_createwithmodules ( edit = False , formsemestre : FormSemestre = None ) :
" Form choix modules / responsables et création formsemestre "
2021-09-27 16:42:14 +02:00
vals = scu . get_request_args ( )
2022-10-01 15:34:39 +02:00
# Fonction accessible à tous, contrôle d'acces à la main:
2021-08-11 00:36:07 +02:00
if not current_user . has_permission ( Permission . ScoImplement ) :
2020-09-26 16:19:37 +02:00
if not edit :
2022-05-22 03:26:39 +02:00
# il faut ScoImplement pour créer un semestre
2020-09-26 16:19:37 +02:00
raise AccessDenied ( " vous n ' avez pas le droit d ' effectuer cette opération " )
else :
2022-10-01 15:34:39 +02:00
if not formsemestre . resp_can_edit or current_user . id not in (
u . id for u in formsemestre . responsables
) :
2020-09-26 16:19:37 +02:00
raise AccessDenied (
" vous n ' avez pas le droit d ' effectuer cette opération "
)
2022-08-31 19:14:21 +02:00
# Liste des enseignants avec form pour affichage / saisie avec suggestion
2021-09-03 18:17:43 +02:00
# attention: il faut prendre ici tous les utilisateurs, même inactifs, car
# les responsables de modules d'anciens semestres peuvent ne plus être actifs.
# Mais la suggestion utilise get_user_list_xml() qui ne suggérera que les actifs.
user_list = sco_users . get_user_list ( with_inactives = True )
2021-08-11 00:36:07 +02:00
uid2display = { } # user_name : forme pour affichage = "NOM Prenom (login)"
2021-09-03 18:17:43 +02:00
for u in user_list :
2021-08-11 00:36:07 +02:00
uid2display [ u . id ] = u . get_nomplogin ( )
allowed_user_names = list ( uid2display . values ( ) ) + [ " " ]
2020-09-26 16:19:37 +02:00
#
2023-01-14 00:05:39 +01:00
if formsemestre :
formation = formsemestre . formation
else :
formation_id = int ( vals [ " formation_id " ] )
formation = Formation . query . get_or_404 ( formation_id )
2022-05-22 03:26:39 +02:00
is_apc = formation . is_apc ( )
2020-09-26 16:19:37 +02:00
if not edit :
2022-01-30 08:13:24 +01:00
initvalues = { " titre " : _default_sem_title ( formation ) }
2023-02-21 11:08:41 +01:00
try :
semestre_id = int ( vals [ " semestre_id " ] )
except ValueError as exc :
raise ScoValueError ( " valeur invalide pour l ' indice de semestre " ) from exc
2022-01-30 08:13:24 +01:00
module_ids_set = set ( )
2020-09-26 16:19:37 +02:00
else :
# setup form init values
2022-10-01 15:34:39 +02:00
initvalues = formsemestre . to_dict ( )
semestre_id = formsemestre . semestre_id
2021-08-11 00:36:07 +02:00
# add associated modules to tf-checked:
2022-01-30 08:13:24 +01:00
module_ids_existing = [ modimpl . module . id for modimpl in formsemestre . modimpls ]
module_ids_set = set ( module_ids_existing )
initvalues [ " tf-checked " ] = [ " MI " + str ( x ) for x in module_ids_existing ]
for modimpl in formsemestre . modimpls :
initvalues [ f " MI { modimpl . module . id } " ] = uid2display . get (
modimpl . responsable_id ,
f " inconnu numéro { modimpl . responsable_id } resp. de { modimpl . id } ! " ,
2020-09-26 16:19:37 +02:00
)
2022-10-01 15:34:39 +02:00
for index , resp in enumerate ( formsemestre . responsables ) :
initvalues [ resp_fields [ index ] ] = uid2display . get ( resp . id )
2020-09-26 16:19:37 +02:00
# Liste des ID de semestres
2022-01-30 08:13:24 +01:00
if formation . type_parcours is not None :
2023-02-12 13:36:47 +01:00
parcours = codes_cursus . get_cursus_from_code ( formation . type_parcours )
2022-10-01 15:34:39 +02:00
nb_sem = parcours . NB_SEM
2021-08-09 11:33:04 +02:00
else :
2022-10-01 15:34:39 +02:00
nb_sem = 10 # fallback, max 10 semestres
if nb_sem == 1 :
2022-01-04 20:03:38 +01:00
semestre_id_list = [ - 1 ]
else :
2022-05-22 03:26:39 +02:00
if edit and is_apc :
2022-01-30 08:13:24 +01:00
# en APC, ne permet pas de changer de semestre
semestre_id_list = [ formsemestre . semestre_id ]
else :
2022-10-01 15:34:39 +02:00
semestre_id_list = list ( range ( 1 , nb_sem + 1 ) )
2022-05-22 03:26:39 +02:00
if not is_apc :
2022-02-28 16:28:08 +01:00
# propose "pas de semestre" seulement en classique
semestre_id_list . insert ( 0 , - 1 )
2022-01-30 08:13:24 +01:00
2020-09-26 16:19:37 +02:00
semestre_id_labels = [ ]
for sid in semestre_id_list :
2022-01-04 20:03:38 +01:00
if sid == - 1 :
2020-09-26 16:19:37 +02:00
semestre_id_labels . append ( " pas de semestres " )
else :
2021-08-30 23:28:15 +02:00
semestre_id_labels . append ( f " S { sid } " )
2022-01-30 23:52:52 +01:00
# Liste des modules dans cette formation
2022-05-22 03:26:39 +02:00
if is_apc :
2022-08-31 19:14:21 +02:00
# BUT: trie par type (res, sae), parcours, numéro
modules = sorted (
formation . modules ,
key = lambda m : m . sort_key_apc ( ) ,
)
2022-01-30 23:52:52 +01:00
else :
modules = (
Module . query . filter (
2023-01-14 00:05:39 +01:00
Module . formation_id == formation . id , UniteEns . id == Module . ue_id
2022-01-30 23:52:52 +01:00
)
. order_by ( Module . module_type , UniteEns . numero , Module . numero )
. all ( )
)
2020-09-26 16:19:37 +02:00
# Pour regroupement des modules par semestres:
semestre_ids = { }
2022-08-31 19:14:21 +02:00
for mod in modules :
semestre_ids [ mod . semestre_id ] = 1
2021-07-09 17:47:06 +02:00
semestre_ids = list ( semestre_ids . keys ( ) )
2020-09-26 16:19:37 +02:00
semestre_ids . sort ( )
2021-08-21 00:24:51 +02:00
modalites = sco_modalites . do_modalite_list ( )
2020-09-26 16:19:37 +02:00
modalites_abbrv = [ m [ " modalite " ] for m in modalites ]
modalites_titles = [ m [ " titre " ] for m in modalites ]
#
modform = [
( " formsemestre_id " , { " input_type " : " hidden " } ) ,
2023-01-14 00:05:39 +01:00
( " formation_id " , { " input_type " : " hidden " , " default " : formation . id } ) ,
2020-09-26 16:19:37 +02:00
(
" date_debut " ,
{
" title " : " Date de début " , # j/m/a
2022-01-10 12:00:02 +01:00
" input_type " : " datedmy " ,
2020-09-26 16:19:37 +02:00
" explanation " : " j/m/a " ,
" size " : 9 ,
" allow_null " : False ,
} ,
) ,
(
" date_fin " ,
{
" title " : " Date de fin " , # j/m/a
2022-01-10 12:00:02 +01:00
" input_type " : " datedmy " ,
2020-09-26 16:19:37 +02:00
" explanation " : " j/m/a " ,
" size " : 9 ,
" allow_null " : False ,
} ,
) ,
2022-09-01 16:55:20 +02:00
* [
(
field ,
{
" input_type " : " text_suggest " ,
" size " : 50 ,
2022-09-02 14:24:37 +02:00
" title " : " (Co-)Directeur(s) des études "
if index
else " Directeur des études " ,
" explanation " : " (facultatif) taper le début du nom et choisir dans le menu "
if index
else " (obligatoire) taper le début du nom et choisir dans le menu " ,
2022-09-01 16:55:20 +02:00
" allowed_values " : allowed_user_names ,
" allow_null " : index , # > 0, # il faut au moins un responsable de semestre
" text_suggest_options " : {
" script " : url_for (
" users.get_user_list_xml " , scodoc_dept = g . scodoc_dept
)
+ " ? " , # "Users/get_user_list_xml?",
" varname " : " start " ,
" json " : False ,
" noresults " : " Valeur invalide ! " ,
" timeout " : 60000 ,
} ,
2020-09-26 16:19:37 +02:00
} ,
2022-09-01 16:55:20 +02:00
)
for index , field in enumerate ( resp_fields )
] ,
2020-09-26 16:19:37 +02:00
(
" titre " ,
{
" size " : 40 ,
" title " : " Nom de ce semestre " ,
2022-05-22 03:26:39 +02:00
" explanation " : f """ n ' indiquez pas les dates, ni le semestre, ni la modalité dans
2021-09-27 10:20:10 +02:00
le titre : ils seront automatiquement ajoutés < input type = " button "
2022-05-22 03:26:39 +02:00
value = " remettre titre par défaut " onClick = " document.tf.titre.value= ' {
_default_sem_title ( formation ) } ' ; " /> " " " ,
2023-01-11 13:37:02 +01:00
" allow_null " : False ,
2020-09-26 16:19:37 +02:00
} ,
) ,
(
" modalite " ,
{
" input_type " : " menu " ,
" title " : " Modalité " ,
" allowed_values " : modalites_abbrv ,
" labels " : modalites_titles ,
} ,
) ,
2022-01-04 20:03:38 +01:00
]
modform . append (
2020-09-26 16:19:37 +02:00
(
" semestre_id " ,
{
" input_type " : " menu " ,
" title " : " Semestre dans la formation " ,
" allowed_values " : semestre_id_list ,
" labels " : semestre_id_labels ,
2022-01-30 08:13:24 +01:00
" explanation " : " en BUT, on ne peut pas modifier le semestre après création "
2022-05-22 03:26:39 +02:00
if is_apc
2022-02-28 17:57:12 +01:00
else " " ,
2022-05-22 03:26:39 +02:00
" attributes " : [ ' onchange= " change_semestre_id(); " ' ] if is_apc else " " ,
2020-09-26 16:19:37 +02:00
} ,
) ,
2022-01-04 20:03:38 +01:00
)
2021-08-20 10:51:42 +02:00
etapes = sco_portal_apogee . get_etapes_apogee_dept ( )
2020-09-26 16:19:37 +02:00
# Propose les etapes renvoyées par le portail
# et ajoute les étapes du semestre qui ne sont pas dans la liste (soit la liste a changé, soit l'étape a été ajoutée manuellement)
etapes_set = { et [ 0 ] for et in etapes }
if edit :
2022-10-01 15:34:39 +02:00
for etape_vdi in formsemestre . etapes_apo_vdi ( ) :
2020-09-26 16:19:37 +02:00
if etape_vdi . etape not in etapes_set :
etapes . append ( ( etape_vdi . etape , " inconnue " ) )
modform . append (
(
" elt_help_apo " ,
{
" title " : " Codes Apogée nécessaires pour inscrire les étudiants et exporter les notes en fin de semestre: " ,
" input_type " : " separator " ,
} ,
)
)
mf_manual = {
" size " : 12 ,
" template " : ' <tr %(item_dom_attr)s ><td class= " tf-fieldlabel " > %(label)s </td><td class= " tf-field " > %(elem)s ' ,
2021-12-29 19:30:49 +01:00
" validator " : lambda val , _ : len ( val ) < APO_CODE_STR_LEN ,
2020-09-26 16:19:37 +02:00
}
if etapes :
mf = {
" input_type " : " menu " ,
" allowed_values " : [ " " ] + [ e [ 0 ] for e in etapes ] ,
" labels " : [ " (aucune) " ] + [ " %s ( %s ) " % ( e [ 1 ] , e [ 0 ] ) for e in etapes ] ,
" template " : ' <tr %(item_dom_attr)s ><td class= " tf-fieldlabel " > %(label)s </td><td class= " tf-field " > %(elem)s ' ,
}
else :
# fallback: code etape libre
mf = mf_manual
2021-02-04 20:02:44 +01:00
for n in range ( 1 , scu . EDIT_NB_ETAPES + 1 ) :
2022-05-22 03:26:39 +02:00
mf [ " title " ] = f " Etape Apogée ( { n } ) "
2020-09-26 16:19:37 +02:00
modform . append ( ( " etape_apo " + str ( n ) , mf . copy ( ) ) )
modform . append (
(
" vdi_apo " + str ( n ) ,
{
" size " : 7 ,
" title " : " Version (VDI): " ,
" template " : ' <span class= " vdi_label " > %(label)s </span><span class= " tf-field " > %(elem)s </span></td></tr> ' ,
} ,
)
)
# Saisie manuelle de l'étape: (seulement si menus)
if etapes :
n = 0
mf = mf_manual
mf [ " title " ] = " Etape Apogée (+) "
modform . append ( ( " etape_apo " + str ( n ) , mf . copy ( ) ) )
modform . append (
(
" vdi_apo " + str ( n ) ,
{
" size " : 7 ,
" title " : " Version (VDI): " ,
" template " : ' <span class= " vdi_label " > %(label)s </span><span class= " tf-field " > %(elem)s </span></td></tr> ' ,
" explanation " : " saisie manuelle si votre étape n ' est pas dans le menu " ,
} ,
)
)
modform . append (
(
" elt_sem_apo " ,
{
" size " : 32 ,
" title " : " Element(s) Apogée: " ,
2022-07-13 11:30:01 +02:00
" explanation " : " associé(s) au résultat du semestre (ex: VRTW1). Inutile en BUT. Séparés par des virgules. " ,
2021-06-13 23:37:14 +02:00
" allow_null " : not sco_preferences . get_preference (
2021-07-28 17:03:54 +02:00
" always_require_apo_sem_codes "
2022-09-30 23:29:06 +02:00
)
2022-10-01 15:34:39 +02:00
or ( formsemestre and formsemestre . modalite == " EXT " ) ,
2020-09-26 16:19:37 +02:00
} ,
)
)
modform . append (
(
" elt_annee_apo " ,
{
" size " : 32 ,
" title " : " Element(s) Apogée: " ,
2022-07-13 11:30:01 +02:00
" explanation " : " associé(s) au résultat de l ' année (ex: VRT1A). Séparés par des virgules. " ,
2021-06-13 23:37:14 +02:00
" allow_null " : not sco_preferences . get_preference (
2021-07-28 17:03:54 +02:00
" always_require_apo_sem_codes "
2022-09-30 23:29:06 +02:00
)
2022-10-01 15:34:39 +02:00
or ( formsemestre and formsemestre . modalite == " EXT " ) ,
2020-09-26 16:19:37 +02:00
} ,
)
)
if edit :
2022-05-22 03:26:39 +02:00
formtit = f """
2023-01-14 00:05:39 +01:00
< p > < a class = " stdlink " href = " { url_for( " notes . formsemestre_edit_uecoefs " ,
2022-10-01 15:34:39 +02:00
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre . id )
} " >Modifier les coefficients des UE capitalisées</a>
< / p >
2022-05-22 03:26:39 +02:00
< h3 > Sélectionner les modules , leurs responsables et les étudiants
à inscrire : < / h3 >
2020-09-26 16:19:37 +02:00
"""
else :
2022-05-22 03:26:39 +02:00
formtit = """ <h3>Sélectionner les modules et leurs responsables</h3>
2022-10-01 15:34:39 +02:00
< p class = " help " >
Si vous avez des parcours ( options ) , dans un premier temps
2022-05-22 03:26:39 +02:00
ne sélectionnez que les modules du tronc commun , puis après inscriptions ,
revenez ajouter les modules de parcours en sélectionnant les groupes d ' étudiants
à y inscrire .
< / p > """
2020-09-26 16:19:37 +02:00
modform + = [
(
" gestion_compensation_lst " ,
{
" input_type " : " checkbox " ,
" title " : " Jurys " ,
" allowed_values " : [ " X " ] ,
" explanation " : " proposer compensations de semestres (parcours DUT) " ,
" labels " : [ " " ] ,
} ,
) ,
(
" gestion_semestrielle_lst " ,
{
" input_type " : " checkbox " ,
" title " : " " ,
" allowed_values " : [ " X " ] ,
" explanation " : " formation semestrialisée (jurys avec semestres décalés) " ,
" labels " : [ " " ] ,
} ,
) ,
]
2021-08-11 00:36:07 +02:00
if current_user . has_permission ( Permission . ScoImplement ) :
2020-09-26 16:19:37 +02:00
modform + = [
(
" resp_can_edit " ,
{
" input_type " : " boolcheckbox " ,
" title " : " Autorisations " ,
" explanation " : " Autoriser le directeur des études à modifier ce semestre " ,
} ,
)
]
modform + = [
(
" resp_can_change_ens " ,
{
" input_type " : " boolcheckbox " ,
" title " : " " ,
" explanation " : " Autoriser le directeur des études à modifier les enseignants " ,
} ,
) ,
(
" ens_can_edit_eval " ,
{
" input_type " : " boolcheckbox " ,
" title " : " " ,
2022-02-28 17:57:12 +01:00
" explanation " : """ Autoriser tous les enseignants associés
à un module à y créer des évaluations """ ,
2020-09-26 16:19:37 +02:00
} ,
) ,
(
" bul_bgcolor " ,
{
" size " : 8 ,
" title " : " Couleur fond des bulletins " ,
" explanation " : " version web seulement (ex: #ffeeee) " ,
2021-12-29 19:30:49 +01:00
" validator " : lambda val , _ : len ( val ) < SHORT_STR_LEN ,
2020-09-26 16:19:37 +02:00
} ,
) ,
(
" bul_publish_xml_lst " ,
{
" input_type " : " checkbox " ,
" title " : " Publication " ,
" allowed_values " : [ " X " ] ,
" explanation " : " publier le bulletin sur le portail étudiants " ,
" labels " : [ " " ] ,
} ,
) ,
2021-09-16 22:24:08 +02:00
(
" block_moyennes " ,
{
" input_type " : " boolcheckbox " ,
" title " : " Bloquer moyennes " ,
" explanation " : " empêcher le calcul des moyennes d ' UE et générale. " ,
} ,
) ,
2022-11-01 17:39:18 +01:00
(
" block_moyenne_generale " ,
{
" input_type " : " boolcheckbox " ,
" title " : " Pas de moyenne générale " ,
" explanation " : " ne pas calculer la moyenne générale indicative (en BUT) " ,
} ,
) ,
2022-05-22 03:26:39 +02:00
]
# Choix des parcours
if is_apc :
ref_comp = formation . referentiel_competence
if ref_comp :
modform + = [
(
" parcours " ,
{
" input_type " : " checkbox " ,
" vertical " : True ,
" dom_id " : " tf_module_parcours " ,
" labels " : [ parcour . libelle for parcour in ref_comp . parcours ] ,
" allowed_values " : [
str ( parcour . id ) for parcour in ref_comp . parcours
] ,
2022-05-28 11:38:22 +02:00
" explanation " : """ Parcours proposés dans ce semestre.
2023-01-26 17:28:36 +01:00
Cocher tous les parcours est exactement équivalent à n ' en cocher aucun:
par exemple , pour un semestre de " tronc commun " , on peut ne pas indiquer de parcours .
Si aucun parcours n ' est coché, toutes les UEs du
programme seront donc considérées , quel que soit leur parcours .
2022-12-17 13:18:10 +01:00
""" ,
2022-05-22 03:26:39 +02:00
} ,
)
]
if edit :
2022-10-01 15:34:39 +02:00
initvalues [ " parcours " ] = [
2022-12-17 14:05:13 +01:00
str ( parcour . id ) for parcour in formsemestre . get_parcours_apc ( )
2022-10-01 15:34:39 +02:00
]
2022-05-22 03:26:39 +02:00
else :
modform + = [
(
" parcours " ,
{
" input_type " : " separator " ,
" title " : f """ <span class= " fontred " > { scu . EMO_WARNING }
Pas de parcours :
< a class = " stdlink " href = " { url_for( ' notes.ue_table ' ,
scodoc_dept = g . scodoc_dept , formation_id = formation . id )
} " >vérifier la formation</a>
< / span > """ ,
} ,
)
]
# Choix des modules
modform + = [
2020-09-26 16:19:37 +02:00
(
" sep " ,
{
" input_type " : " separator " ,
" title " : " " ,
2022-05-22 03:26:39 +02:00
" template " : f " </table> { formtit } <table> " ,
2020-09-26 16:19:37 +02:00
} ,
) ,
]
nbmod = 0
2022-02-28 17:57:12 +01:00
2020-09-26 16:19:37 +02:00
for semestre_id in semestre_ids :
2022-05-22 03:26:39 +02:00
if is_apc :
# pour restreindre l'édition aux modules du semestre sélectionné
2022-03-01 10:16:34 +01:00
tr_class = f ' class= " sem { semestre_id } " '
2022-02-28 17:57:12 +01:00
else :
tr_class = " "
if edit :
templ_sep = f """ <tr { tr_class } ><td>%(label)s</td><td><b>Responsable</b></td><td><b>Inscrire</b></td></tr> """
else :
templ_sep = (
f """ <tr { tr_class } ><td>%(label)s</td><td><b>Responsable</b></td></tr> """
)
2020-09-26 16:19:37 +02:00
modform . append (
(
" sep " ,
{
" input_type " : " separator " ,
2022-05-22 03:26:39 +02:00
" title " : f " <b>Semestre { semestre_id } </b> " ,
2020-09-26 16:19:37 +02:00
" template " : templ_sep ,
} ,
)
)
2022-08-31 19:14:21 +02:00
for mod in modules :
if mod . semestre_id == semestre_id and (
2022-01-30 08:13:24 +01:00
( not edit ) # creation => tous modules
2022-05-22 03:26:39 +02:00
or ( not is_apc ) # pas BUT, on peut mixer les semestres
2022-01-30 08:13:24 +01:00
or ( semestre_id == formsemestre . semestre_id ) # module du semestre
2022-08-31 19:14:21 +02:00
or ( mod . id in module_ids_set ) # module déjà présent
2022-01-30 08:13:24 +01:00
) :
2020-09-26 16:19:37 +02:00
nbmod + = 1
if edit :
2022-08-31 19:14:21 +02:00
select_name = f " { mod . id } !group_id "
2020-09-26 16:19:37 +02:00
def opt_selected ( gid ) :
2021-09-27 10:20:10 +02:00
if gid == vals . get ( select_name ) :
2020-09-26 16:19:37 +02:00
return " selected "
else :
return " "
2022-08-31 19:14:21 +02:00
if mod . id in module_ids_set :
# pas de menu inscription si le module est déjà présent
2020-09-26 16:19:37 +02:00
disabled = " disabled "
else :
disabled = " "
2022-08-31 19:14:21 +02:00
fcg = f ' <select name= " { select_name } " { disabled } > '
2022-10-01 15:34:39 +02:00
default_group_id = sco_groups . get_default_group ( formsemestre . id )
2022-08-31 19:14:21 +02:00
fcg + = f """ <option value= " { default_group_id } " {
opt_selected ( default_group_id ) } > Tous < / option > """
fcg + = f ' <option value= " " { opt_selected ( " " ) } >Aucun</option> '
for partition in formsemestre . partitions :
if partition . partition_name is not None :
for group in partition . groups :
# Si le module n'est associé qu'à un parcours, propose d'y inscrire les étudiants directement
if (
partition . partition_name == scu . PARTITION_PARCOURS
and len ( mod . parcours ) == 1
and group . group_name == mod . parcours [ 0 ] . code
) :
selected = " selected "
else :
selected = opt_selected ( group . id )
# print(
# f"{partition.partition_name} {group.group_name} {selected}"
# )
fcg + = f """ <option value= " { group . id } " { selected
} > { partition . partition_name } { group . group_name } < / option > """
2020-09-26 16:19:37 +02:00
fcg + = " </select> "
2022-05-22 03:26:39 +02:00
itemtemplate = f """ <tr { tr_class } >
< td class = " tf-fieldlabel " > % ( label ) s < / td >
< td class = " tf-field " > % ( elem ) s < / td >
< td > { fcg } < / td >
< / tr > """
2020-09-26 16:19:37 +02:00
else :
2022-05-22 03:26:39 +02:00
itemtemplate = f """ <tr { tr_class } >
< td class = " tf-fieldlabel " > % ( label ) s < / td >
< td class = " tf-field " > % ( elem ) s < / td >
< / tr > """
2020-09-26 16:19:37 +02:00
modform . append (
(
2022-08-31 19:14:21 +02:00
" MI " + str ( mod . id ) ,
2020-09-26 16:19:37 +02:00
{
" input_type " : " text_suggest " ,
" size " : 50 ,
" withcheckbox " : True ,
2022-08-31 19:14:21 +02:00
" title " : " %s %s " % ( mod . code or " " , mod . titre or " " ) ,
2020-09-26 16:19:37 +02:00
" allowed_values " : allowed_user_names ,
" template " : itemtemplate ,
" text_suggest_options " : {
2021-07-05 23:04:39 +02:00
" script " : url_for (
" users.get_user_list_xml " , scodoc_dept = g . scodoc_dept
)
+ " ? " ,
2020-09-26 16:19:37 +02:00
" varname " : " start " ,
" json " : False ,
" noresults " : " Valeur invalide ! " ,
" timeout " : 60000 ,
} ,
} ,
)
)
if nbmod == 0 :
modform . append (
(
" sep " ,
{
" input_type " : " separator " ,
" title " : " aucun module dans cette formation !!! " ,
} ,
)
)
if edit :
2022-03-29 23:47:26 +02:00
submitlabel = " Modifier ce semestre "
2020-09-26 16:19:37 +02:00
else :
submitlabel = " Créer ce semestre de formation "
#
# Etapes:
if edit :
n = 1
2022-10-01 15:34:39 +02:00
for etape_vdi in formsemestre . etapes_apo_vdi ( ) :
2020-09-26 16:19:37 +02:00
initvalues [ " etape_apo " + str ( n ) ] = etape_vdi . etape
initvalues [ " vdi_apo " + str ( n ) ] = etape_vdi . vdi
n + = 1
#
2021-08-11 00:36:07 +02:00
initvalues [ " gestion_compensation " ] = initvalues . get ( " gestion_compensation " , False )
if initvalues [ " gestion_compensation " ] :
2020-09-26 16:19:37 +02:00
initvalues [ " gestion_compensation_lst " ] = [ " X " ]
else :
initvalues [ " gestion_compensation_lst " ] = [ ]
2021-09-27 10:20:10 +02:00
if vals . get ( " tf_submitted " , False ) and " gestion_compensation_lst " not in vals :
vals [ " gestion_compensation_lst " ] = [ ]
2020-09-26 16:19:37 +02:00
2021-08-11 00:36:07 +02:00
initvalues [ " gestion_semestrielle " ] = initvalues . get ( " gestion_semestrielle " , False )
if initvalues [ " gestion_semestrielle " ] :
2020-09-26 16:19:37 +02:00
initvalues [ " gestion_semestrielle_lst " ] = [ " X " ]
else :
initvalues [ " gestion_semestrielle_lst " ] = [ ]
2021-09-27 10:20:10 +02:00
if vals . get ( " tf_submitted " , False ) and " gestion_semestrielle_lst " not in vals :
vals [ " gestion_semestrielle_lst " ] = [ ]
2020-09-26 16:19:37 +02:00
2021-08-11 00:36:07 +02:00
initvalues [ " bul_hide_xml " ] = initvalues . get ( " bul_hide_xml " , False )
if not initvalues [ " bul_hide_xml " ] :
2020-09-26 16:19:37 +02:00
initvalues [ " bul_publish_xml_lst " ] = [ " X " ]
else :
initvalues [ " bul_publish_xml_lst " ] = [ ]
2021-09-27 10:20:10 +02:00
if vals . get ( " tf_submitted " , False ) and " bul_publish_xml_lst " not in vals :
vals [ " bul_publish_xml_lst " ] = [ ]
2020-09-26 16:19:37 +02:00
#
tf = TrivialFormulator (
2021-09-18 10:10:02 +02:00
request . base_url ,
2021-09-27 10:20:10 +02:00
vals ,
2020-09-26 16:19:37 +02:00
modform ,
submitlabel = submitlabel ,
cancelbutton = " Annuler " ,
top_buttons = True ,
initvalues = initvalues ,
)
msg = " "
if tf [ 0 ] == 1 :
# check dates
2021-02-03 22:00:41 +01:00
if ndb . DateDMYtoISO ( tf [ 2 ] [ " date_debut " ] ) > ndb . DateDMYtoISO ( tf [ 2 ] [ " date_fin " ] ) :
2020-09-26 16:19:37 +02:00
msg = ' <ul class= " tf-msg " ><li class= " tf-msg " >Dates de début et fin incompatibles !</li></ul> '
2022-10-01 15:34:39 +02:00
2022-09-30 23:29:06 +02:00
if (
2022-10-01 15:34:39 +02:00
sco_preferences . get_preference ( " always_require_apo_sem_codes " )
2022-09-30 23:29:06 +02:00
and not any (
[ tf [ 2 ] [ " etape_apo " + str ( n ) ] for n in range ( 0 , scu . EDIT_NB_ETAPES + 1 ) ]
)
2022-10-01 15:34:39 +02:00
# n'impose pas d'Apo pour les sem. extérieurs
and ( ( formsemestre is None ) or formsemestre . modalite != " EXT " )
2020-09-26 16:19:37 +02:00
) :
msg = ' <ul class= " tf-msg " ><li class= " tf-msg " >Code étape Apogée manquant</li></ul> '
2020-12-16 01:34:08 +01:00
2020-09-26 16:19:37 +02:00
if tf [ 0 ] == 0 or msg :
2022-01-30 08:13:24 +01:00
return f """ <p>Formation <a class= " discretelink " href= " {
2022-10-01 15:34:39 +02:00
url_for ( " notes.ue_table " , scodoc_dept = g . scodoc_dept ,
2023-01-14 00:05:39 +01:00
formation_id = formation . id )
2022-10-01 15:34:39 +02:00
} " ><em> {formation.titre} </em> ( {formation.acronyme} ), version {
formation . version } , code { formation . formation_code } < / a >
2022-01-30 08:13:24 +01:00
< / p >
{ msg }
{ tf [ 1 ] }
"""
2020-09-26 16:19:37 +02:00
elif tf [ 0 ] == - 1 :
2023-07-05 19:18:41 +02:00
if formsemestre :
return redirect (
url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre . id ,
)
2023-06-28 21:25:38 +02:00
)
2023-07-05 19:18:41 +02:00
else :
return redirect ( url_for ( " notes.index_html " , scodoc_dept = g . scodoc_dept ) )
2020-09-26 16:19:37 +02:00
else :
if tf [ 2 ] [ " gestion_compensation_lst " ] :
2021-08-11 00:36:07 +02:00
tf [ 2 ] [ " gestion_compensation " ] = True
2020-09-26 16:19:37 +02:00
else :
2021-08-11 00:36:07 +02:00
tf [ 2 ] [ " gestion_compensation " ] = False
2020-09-26 16:19:37 +02:00
if tf [ 2 ] [ " gestion_semestrielle_lst " ] :
2021-08-11 00:36:07 +02:00
tf [ 2 ] [ " gestion_semestrielle " ] = True
2020-09-26 16:19:37 +02:00
else :
2021-08-11 00:36:07 +02:00
tf [ 2 ] [ " gestion_semestrielle " ] = False
2020-09-26 16:19:37 +02:00
if tf [ 2 ] [ " bul_publish_xml_lst " ] :
2021-08-11 00:36:07 +02:00
tf [ 2 ] [ " bul_hide_xml " ] = False
2020-09-26 16:19:37 +02:00
else :
2021-08-11 00:36:07 +02:00
tf [ 2 ] [ " bul_hide_xml " ] = True
2020-09-26 16:19:37 +02:00
# remap les identifiants de responsables:
2022-09-01 16:55:20 +02:00
for field in resp_fields :
tf [ 2 ] [ field ] = User . get_user_id_from_nomplogin ( tf [ 2 ] [ field ] )
tf [ 2 ] [ " responsables " ] = [ ]
for field in resp_fields :
if tf [ 2 ] [ field ] :
tf [ 2 ] [ " responsables " ] . append ( tf [ 2 ] [ field ] )
2020-09-26 16:19:37 +02:00
for module_id in tf [ 2 ] [ " tf-checked " ] :
2021-08-11 00:36:07 +02:00
mod_resp_id = User . get_user_id_from_nomplogin ( tf [ 2 ] [ module_id ] )
2020-09-26 16:19:37 +02:00
if mod_resp_id is None :
2022-05-22 03:26:39 +02:00
# Si un module n'a pas de responsable (ou inconnu),
# l'affecte au 1er directeur des etudes:
2020-09-26 16:19:37 +02:00
mod_resp_id = tf [ 2 ] [ " responsable_id " ]
tf [ 2 ] [ module_id ] = mod_resp_id
# etapes:
tf [ 2 ] [ " etapes " ] = [ ]
if etapes : # menus => case supplementaire pour saisie manuelle, indicée 0
start_i = 0
else :
start_i = 1
2021-02-04 20:02:44 +01:00
for n in range ( start_i , scu . EDIT_NB_ETAPES + 1 ) :
2020-09-26 16:19:37 +02:00
tf [ 2 ] [ " etapes " ] . append (
ApoEtapeVDI (
etape = tf [ 2 ] [ " etape_apo " + str ( n ) ] , vdi = tf [ 2 ] [ " vdi_apo " + str ( n ) ]
)
)
2022-01-30 08:13:24 +01:00
# Modules sélectionnés:
# (retire le "MI" du début du nom de champs)
module_ids_checked = [ int ( x [ 2 : ] ) for x in tf [ 2 ] [ " tf-checked " ] ]
2022-02-02 10:49:34 +01:00
_formsemestre_check_ue_bonus_unicity ( module_ids_checked )
2020-09-26 16:19:37 +02:00
if not edit :
2022-05-22 03:26:39 +02:00
if is_apc :
2022-01-30 08:13:24 +01:00
_formsemestre_check_module_list (
module_ids_checked , tf [ 2 ] [ " semestre_id " ]
)
# création du semestre
2021-07-29 16:31:15 +02:00
formsemestre_id = sco_formsemestre . do_formsemestre_create ( tf [ 2 ] )
2022-01-30 08:13:24 +01:00
# création des modules
for module_id in module_ids_checked :
2020-09-26 16:19:37 +02:00
modargs = {
2022-01-30 08:13:24 +01:00
" module_id " : module_id ,
2020-09-26 16:19:37 +02:00
" formsemestre_id " : formsemestre_id ,
2022-01-30 08:13:24 +01:00
" responsable_id " : tf [ 2 ] [ f " MI { module_id } " ] ,
2020-09-26 16:19:37 +02:00
}
2021-08-20 01:09:55 +02:00
_ = sco_moduleimpl . do_moduleimpl_create ( modargs )
2020-09-26 16:19:37 +02:00
else :
2022-01-30 08:13:24 +01:00
# Modification du semestre:
2020-09-26 16:19:37 +02:00
# on doit creer les modules nouvellement selectionnés
2022-01-30 08:13:24 +01:00
# modifier ceux à modifier, et DETRUIRE ceux qui ne sont plus selectionnés.
# Note: la destruction échouera s'il y a des objets dépendants
# (eg des évaluations définies)
module_ids_tocreate = [
x for x in module_ids_checked if not x in module_ids_existing
]
2022-05-22 03:26:39 +02:00
if is_apc :
2022-01-30 08:13:24 +01:00
_formsemestre_check_module_list (
module_ids_tocreate , tf [ 2 ] [ " semestre_id " ]
)
# modules existants à modifier
module_ids_toedit = [
x for x in module_ids_checked if x in module_ids_existing
]
# modules à détruire
module_ids_todelete = [
x for x in module_ids_existing if not x in module_ids_checked
]
#
2021-08-19 10:28:35 +02:00
sco_formsemestre . do_formsemestre_edit ( tf [ 2 ] )
2020-09-26 16:19:37 +02:00
#
msg = [ ]
2022-01-30 08:13:24 +01:00
for module_id in module_ids_tocreate :
2020-09-26 16:19:37 +02:00
modargs = {
" module_id " : module_id ,
2022-10-01 15:34:39 +02:00
" formsemestre_id " : formsemestre . id ,
2021-08-11 00:36:07 +02:00
" responsable_id " : tf [ 2 ] [ " MI " + str ( module_id ) ] ,
2020-09-26 16:19:37 +02:00
}
2021-08-20 01:09:55 +02:00
moduleimpl_id = sco_moduleimpl . do_moduleimpl_create ( modargs )
2021-10-16 19:20:36 +02:00
mod = sco_edit_module . module_list ( { " module_id " : module_id } ) [ 0 ]
2022-02-14 10:05:55 +01:00
msg + = [
" création de %s ( %s ) " % ( mod [ " code " ] or " ? " , mod [ " titre " ] or " ? " )
]
2020-09-26 16:19:37 +02:00
# INSCRIPTIONS DES ETUDIANTS
log (
' inscription module: %s = " %s " '
% ( " %s !group_id " % module_id , tf [ 2 ] [ " %s !group_id " % module_id ] )
)
group_id = tf [ 2 ] [ " %s !group_id " % module_id ]
if group_id :
etudids = [
2021-08-19 10:28:35 +02:00
x [ " etudid " ] for x in sco_groups . get_group_members ( group_id )
2020-09-26 16:19:37 +02:00
]
log (
" inscription module:module_id= %s ,moduleimpl_id= %s : %s "
% ( module_id , moduleimpl_id , etudids )
)
2021-02-22 10:17:44 +01:00
sco_moduleimpl . do_moduleimpl_inscrit_etuds (
moduleimpl_id ,
2022-10-01 15:34:39 +02:00
formsemestre . id ,
2021-02-22 10:17:44 +01:00
etudids ,
2020-09-26 16:19:37 +02:00
)
msg + = [
" inscription de %d étudiants au module %s "
2022-02-14 10:05:55 +01:00
% ( len ( etudids ) , mod [ " code " ] or " (module sans code) " )
2020-09-26 16:19:37 +02:00
]
else :
log (
" inscription module:module_id= %s ,moduleimpl_id= %s : aucun etudiant inscrit "
% ( module_id , moduleimpl_id )
)
#
2022-01-30 08:13:24 +01:00
ok , diag = formsemestre_delete_moduleimpls (
2022-10-01 15:34:39 +02:00
formsemestre . id , module_ids_todelete
2022-01-30 08:13:24 +01:00
)
2020-09-26 16:19:37 +02:00
msg + = diag
2022-01-30 08:13:24 +01:00
for module_id in module_ids_toedit :
2021-10-15 14:00:51 +02:00
moduleimpl_id = sco_moduleimpl . moduleimpl_list (
2022-10-01 15:34:39 +02:00
formsemestre_id = formsemestre . id , module_id = module_id
2020-09-26 16:19:37 +02:00
) [ 0 ] [ " moduleimpl_id " ]
modargs = {
" moduleimpl_id " : moduleimpl_id ,
" module_id " : module_id ,
2022-10-01 15:34:39 +02:00
" formsemestre_id " : formsemestre . id ,
2021-08-11 00:36:07 +02:00
" responsable_id " : tf [ 2 ] [ " MI " + str ( module_id ) ] ,
2020-09-26 16:19:37 +02:00
}
2021-01-17 22:31:28 +01:00
sco_moduleimpl . do_moduleimpl_edit (
2022-10-01 15:34:39 +02:00
modargs , formsemestre_id = formsemestre . id
2021-01-17 22:31:28 +01:00
)
2021-10-16 19:20:36 +02:00
mod = sco_edit_module . module_list ( { " module_id " : module_id } ) [ 0 ]
2022-05-28 11:38:22 +02:00
# --- Association des parcours
2022-10-01 15:34:39 +02:00
if formsemestre is None :
2023-03-20 11:17:38 +01:00
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
2022-05-22 03:26:39 +02:00
if " parcours " in tf [ 2 ] :
formsemestre . parcours = [
2023-07-11 06:57:38 +02:00
db . session . get ( ApcParcours , int ( parcour_id_str ) )
2022-05-22 03:26:39 +02:00
for parcour_id_str in tf [ 2 ] [ " parcours " ]
]
db . session . add ( formsemestre )
db . session . commit ( )
2022-05-28 11:38:22 +02:00
# --- Crée ou met à jour les groupes de parcours BUT
formsemestre . setup_parcours_groups ( )
2022-11-01 19:25:15 +01:00
# peut être nécessaire dans certains cas:
formsemestre . update_inscriptions_parcours_from_groups ( )
2022-05-22 03:26:39 +02:00
# --- Fin
if edit :
if msg :
2022-10-01 15:34:39 +02:00
return f """
< div class = " ue_warning " > < span > Attention ! < ul >
< li >
{ " </li><li> " . join ( msg ) }
< / li >
< / ul > < / span >
< / div >
{ " <p>Modification effectuée</p> " if ok
else " <p>Modules non modifiés</p> "
}
< a class = " stdlink " href = " {
url_for ( ' notes.formsemestre_status ' ,
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre . id )
} " >retour au tableau de bord</a>
"""
2022-05-22 03:26:39 +02:00
else :
2022-10-01 15:34:39 +02:00
flash ( " Semestre modifié " )
2022-05-22 03:26:39 +02:00
return flask . redirect (
2022-10-01 15:34:39 +02:00
url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre . id ,
2022-12-17 14:05:13 +01:00
check_parcours = 0 ,
2022-10-01 15:34:39 +02:00
)
2022-05-22 03:26:39 +02:00
)
else :
flash ( " Nouveau semestre créé " )
return flask . redirect (
url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
2022-10-01 15:34:39 +02:00
formsemestre_id = formsemestre . id ,
2022-05-22 03:26:39 +02:00
)
)
2020-09-26 16:19:37 +02:00
2022-01-30 08:13:24 +01:00
def _formsemestre_check_module_list ( module_ids , semestre_idx ) :
""" En APC: Vérifie que tous les modules de la liste
sont dans le semestre indiqué .
Sinon , raise ScoValueError .
"""
# vérification de la cohérence / modules / semestre
mod_sems_idx = {
Module . query . get_or_404 ( module_id ) . ue . semestre_idx for module_id in module_ids
}
if mod_sems_idx and mod_sems_idx != { semestre_idx } :
2022-09-08 01:20:04 +02:00
modules = [ Module . query . get_or_404 ( module_id ) for module_id in module_ids ]
log (
f """ _formsemestre_check_module_list:
{ chr ( 10 ) . join ( str ( module ) + " " + str ( module . ue ) for module in modules ) }
"""
)
for module in modules :
log (
f " { module . code } \t semestre_id= { module . semestre_id } \t ue.semestre_idx= { module . ue . semestre_idx } "
)
2022-01-30 08:13:24 +01:00
raise ScoValueError (
2022-09-08 01:20:04 +02:00
f " Les modules sélectionnés ne sont pas tous dans le semestre choisi (S { semestre_idx } ) ! " ,
2022-01-30 08:13:24 +01:00
dest_url = " javascript:history.back(); " ,
)
2022-02-02 10:49:34 +01:00
def _formsemestre_check_ue_bonus_unicity ( module_ids ) :
""" Vérifie qu ' il n ' y a qu ' une seule UE bonus associée aux modules choisis """
ues = [ Module . query . get_or_404 ( module_id ) . ue for module_id in module_ids ]
2023-02-12 13:36:47 +01:00
ues_bonus = { ue . id for ue in ues if ue . type == codes_cursus . UE_SPORT }
2022-02-02 10:49:34 +01:00
if len ( ues_bonus ) > 1 :
raise ScoValueError (
""" Les modules de bonus sélectionnés ne sont pas tous dans la même UE bonus.
Changez la sélection ou modifiez la structure du programme de formation . """ ,
dest_url = " javascript:history.back(); " ,
)
2021-08-20 01:09:55 +02:00
def formsemestre_delete_moduleimpls ( formsemestre_id , module_ids_to_del ) :
2020-09-26 16:19:37 +02:00
""" Delete moduleimpls
2020-12-16 01:34:08 +01:00
module_ids_to_del : list of module_id ( warning : not moduleimpl )
Moduleimpls must have no associated evaluations .
"""
2020-09-26 16:19:37 +02:00
ok = True
msg = [ ]
for module_id in module_ids_to_del :
2023-07-11 06:57:38 +02:00
module = db . session . get ( Module , module_id )
2022-09-14 10:35:51 +02:00
if module is None :
continue # ignore invalid ids
modimpls = ModuleImpl . query . filter_by (
2021-08-20 01:09:55 +02:00
formsemestre_id = formsemestre_id , module_id = module_id
2022-09-14 10:35:51 +02:00
)
for modimpl in modimpls :
nb_evals = modimpl . evaluations . count ( )
if nb_evals > 0 :
msg + = [
f """ <b>impossible de supprimer { module . code } ( { module . titre or " " } )
car il y a { nb_evals } évaluations définies
( < a href = " {
url_for ( " notes.moduleimpl_status " , scodoc_dept = g . scodoc_dept , moduleimpl_id = modimpl . id )
} " class= " stdlink " >supprimez-les d \' abord</a>)</b> " " "
]
ok = False
else :
msg + = [ f """ suppression de { module . code } ( { module . titre or " " } ) """ ]
db . session . delete ( modimpl )
if ok :
db . session . commit ( )
else :
db . session . rollback ( )
2020-09-26 16:19:37 +02:00
return ok , msg
2021-09-27 10:20:10 +02:00
def formsemestre_clone ( formsemestre_id ) :
2020-09-26 16:19:37 +02:00
"""
Formulaire clonage 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
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
2021-09-03 18:17:43 +02:00
user_list = sco_users . get_user_list ( )
2021-08-11 00:36:07 +02:00
uid2display = { } # user_name : forme pour affichage = "NOM Prenom (login)"
2021-09-03 18:17:43 +02:00
for u in user_list :
2021-08-11 00:36:07 +02:00
uid2display [ u . id ] = u . get_nomplogin ( )
allowed_user_names = list ( uid2display . values ( ) ) + [ " " ]
2020-09-26 16:19:37 +02:00
initvalues = {
" formsemestre_id " : sem [ " formsemestre_id " ] ,
2021-08-11 00:36:07 +02:00
" responsable_id " : uid2display . get (
2020-09-26 16:19:37 +02:00
sem [ " responsables " ] [ 0 ] , sem [ " responsables " ] [ 0 ]
) ,
}
H = [
2021-06-13 19:12:20 +02:00
html_sco_header . html_sem_header (
2020-09-26 16:19:37 +02:00
" Copie du semestre " ,
javascripts = [ " libjs/AutoSuggest.js " ] ,
cssstyles = [ " css/autosuggest_inquisitor.css " ] ,
bodyOnLoad = " init_tf_form( ' ' ) " ,
) ,
""" <p class= " help " >Cette opération duplique un semestre: on reprend les mêmes modules et responsables. Aucun étudiant n ' est inscrit.</p> """ ,
]
descr = [
( " formsemestre_id " , { " input_type " : " hidden " } ) ,
(
" date_debut " ,
{
" title " : " Date de début " , # j/m/a
2022-01-10 12:00:02 +01:00
" input_type " : " datedmy " ,
2020-09-26 16:19:37 +02:00
" explanation " : " j/m/a " ,
" size " : 9 ,
" allow_null " : False ,
} ,
) ,
(
" date_fin " ,
{
" title " : " Date de fin " , # j/m/a
2022-01-10 12:00:02 +01:00
" input_type " : " datedmy " ,
2020-09-26 16:19:37 +02:00
" explanation " : " j/m/a " ,
" size " : 9 ,
" allow_null " : False ,
} ,
) ,
(
" responsable_id " ,
{
" input_type " : " text_suggest " ,
" size " : 50 ,
" title " : " Directeur des études " ,
" explanation " : " taper le début du nom et choisir dans le menu " ,
" allowed_values " : allowed_user_names ,
" allow_null " : False ,
" text_suggest_options " : {
2021-07-05 23:04:39 +02:00
" script " : url_for (
" users.get_user_list_xml " , scodoc_dept = g . scodoc_dept
)
+ " ? " ,
2020-09-26 16:19:37 +02:00
" varname " : " start " ,
" json " : False ,
" noresults " : " Valeur invalide ! " ,
" timeout " : 60000 ,
} ,
} ,
) ,
(
" clone_evaluations " ,
{
" title " : " Copier aussi les évaluations " ,
" input_type " : " boolcheckbox " ,
" explanation " : " copie toutes les évaluations, sans les dates (ni les notes!) " ,
} ,
) ,
(
" clone_partitions " ,
{
" title " : " Copier aussi les partitions " ,
" input_type " : " boolcheckbox " ,
" explanation " : " copie toutes les partitions (sans les étudiants!) " ,
} ,
) ,
]
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 ,
submitlabel = " Dupliquer ce semestre " ,
cancelbutton = " Annuler " ,
initvalues = initvalues ,
)
msg = " "
if tf [ 0 ] == 1 :
# check dates
2021-02-03 22:00:41 +01:00
if ndb . DateDMYtoISO ( tf [ 2 ] [ " date_debut " ] ) > ndb . DateDMYtoISO ( tf [ 2 ] [ " date_fin " ] ) :
2020-09-26 16:19:37 +02:00
msg = ' <ul class= " tf-msg " ><li class= " tf-msg " >Dates de début et fin incompatibles !</li></ul> '
if tf [ 0 ] == 0 or msg :
2021-07-29 10:19:00 +02:00
return " " . join ( H ) + msg + tf [ 1 ] + html_sco_header . sco_footer ( )
2020-09-26 16:19:37 +02:00
elif tf [ 0 ] == - 1 : # cancel
2021-07-31 18:01:10 +02:00
return flask . redirect (
2020-09-26 16:19:37 +02:00
" formsemestre_status?formsemestre_id= %s " % formsemestre_id
)
else :
new_formsemestre_id = do_formsemestre_clone (
formsemestre_id ,
2021-08-11 00:36:07 +02:00
User . get_user_id_from_nomplogin ( tf [ 2 ] [ " responsable_id " ] ) ,
2020-09-26 16:19:37 +02:00
tf [ 2 ] [ " date_debut " ] ,
tf [ 2 ] [ " date_fin " ] ,
clone_evaluations = tf [ 2 ] [ " clone_evaluations " ] ,
clone_partitions = tf [ 2 ] [ " clone_partitions " ] ,
)
2023-04-15 10:50:20 +02:00
flash ( " Nouveau semestre créé " )
2021-07-31 18:01:10 +02:00
return flask . redirect (
2023-04-15 10:50:20 +02:00
url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = new_formsemestre_id ,
)
2020-09-26 16:19:37 +02:00
)
def do_formsemestre_clone (
orig_formsemestre_id ,
responsable_id , # new resp.
date_debut ,
date_fin , # 'dd/mm/yyyy'
clone_evaluations = False ,
clone_partitions = False ,
) :
""" Clone a semestre: make copy, same modules, same options, same resps, same partitions.
2020-12-16 01:34:08 +01:00
New dates , responsable_id
2020-09-26 16:19:37 +02:00
"""
2023-03-21 21:14:38 +01:00
log ( f " do_formsemestre_clone: { orig_formsemestre_id } " )
2023-01-24 00:35:15 +01:00
formsemestre_orig : FormSemestre = FormSemestre . query . get_or_404 (
orig_formsemestre_id
)
2021-08-19 10:28:35 +02:00
orig_sem = sco_formsemestre . get_formsemestre ( orig_formsemestre_id )
2021-06-15 13:59:56 +02:00
cnx = ndb . GetDBConnexion ( )
2020-09-26 16:19:37 +02:00
# 1- create sem
args = orig_sem . copy ( )
del args [ " formsemestre_id " ]
args [ " responsables " ] = [ responsable_id ]
args [ " date_debut " ] = date_debut
args [ " date_fin " ] = date_fin
args [ " etat " ] = 1 # non verrouillé
2021-07-29 16:31:15 +02:00
formsemestre_id = sco_formsemestre . do_formsemestre_create ( args )
2023-01-24 00:35:15 +01:00
log ( f " created formsemestre { formsemestre_id } " )
2023-07-11 06:57:38 +02:00
formsemestre : FormSemestre = db . session . get ( FormSemestre , formsemestre_id )
2020-09-26 16:19:37 +02:00
# 2- create moduleimpls
2021-10-15 14:00:51 +02:00
mods_orig = sco_moduleimpl . moduleimpl_list ( formsemestre_id = orig_formsemestre_id )
2020-09-26 16:19:37 +02:00
for mod_orig in mods_orig :
args = mod_orig . copy ( )
args [ " formsemestre_id " ] = formsemestre_id
2021-08-20 01:09:55 +02:00
mid = sco_moduleimpl . do_moduleimpl_create ( args )
2020-09-26 16:19:37 +02:00
# copy notes_modules_enseignants
2021-01-17 22:31:28 +01:00
ens = sco_moduleimpl . do_ens_list (
2021-08-20 01:09:55 +02:00
args = { " moduleimpl_id " : mod_orig [ " moduleimpl_id " ] }
2021-01-17 22:31:28 +01:00
)
2020-09-26 16:19:37 +02:00
for e in ens :
args = e . copy ( )
args [ " moduleimpl_id " ] = mid
2021-08-20 01:09:55 +02:00
sco_moduleimpl . do_ens_create ( args )
2020-09-26 16:19:37 +02:00
# optionally, copy evaluations
if clone_evaluations :
2021-12-16 22:54:24 +01:00
for e in Evaluation . query . filter_by (
moduleimpl_id = mod_orig [ " moduleimpl_id " ]
) :
# copie en enlevant la date
2023-08-25 17:58:57 +02:00
new_eval = e . clone (
not_copying = ( " date_debut " , " date_fin " , " moduleimpl_id " )
)
2021-12-16 22:54:24 +01:00
new_eval . moduleimpl_id = mid
# Copie les poids APC de l'évaluation
new_eval . set_ue_poids_dict ( e . get_ue_poids_dict ( ) )
db . session . commit ( )
2020-09-26 16:19:37 +02:00
# 3- copy uecoefs
2021-01-17 22:31:28 +01:00
objs = sco_formsemestre . formsemestre_uecoef_list (
cnx , args = { " formsemestre_id " : orig_formsemestre_id }
)
2020-09-26 16:19:37 +02:00
for obj in objs :
args = obj . copy ( )
args [ " formsemestre_id " ] = formsemestre_id
2021-02-07 09:10:26 +01:00
_ = sco_formsemestre . formsemestre_uecoef_create ( cnx , args )
2020-09-26 16:19:37 +02:00
# NB: don't copy notes_formsemestre_custommenu (usually specific)
# 4- Copy new style preferences
2021-07-28 17:03:54 +02:00
prefs = sco_preferences . SemPreferences ( orig_formsemestre_id )
2020-09-26 16:19:37 +02:00
if orig_formsemestre_id in prefs . base_prefs . prefs :
for pname in prefs . base_prefs . prefs [ orig_formsemestre_id ] :
if not prefs . is_global ( pname ) :
pvalue = prefs [ pname ]
2020-12-16 01:34:08 +01:00
try :
prefs . base_prefs . set ( formsemestre_id , pname , pvalue )
2021-07-12 10:51:45 +02:00
except ValueError :
log (
" do_formsemestre_clone: ignoring old preference %s = %s for %s "
% ( pname , pvalue , formsemestre_id )
)
2020-09-26 16:19:37 +02:00
# 5- Copy formules utilisateur
objs = sco_compute_moy . formsemestre_ue_computation_expr_list (
cnx , args = { " formsemestre_id " : orig_formsemestre_id }
)
for obj in objs :
args = obj . copy ( )
args [ " formsemestre_id " ] = formsemestre_id
2021-02-07 09:10:26 +01:00
_ = sco_compute_moy . formsemestre_ue_computation_expr_create ( cnx , args )
2020-09-26 16:19:37 +02:00
2023-01-24 00:35:15 +01:00
# 6- Copie les parcours
formsemestre . parcours = formsemestre_orig . parcours
db . session . add ( formsemestre )
db . session . commit ( )
# 7- Copy partitions and groups
2020-09-26 16:19:37 +02:00
if clone_partitions :
2021-10-12 16:05:50 +02:00
sco_groups_copy . clone_partitions_and_groups (
orig_formsemestre_id , formsemestre_id
)
2020-09-26 16:19:37 +02:00
return formsemestre_id
2021-09-27 10:20:10 +02:00
def formsemestre_delete ( formsemestre_id ) :
2020-09-26 16:19:37 +02:00
""" Delete a formsemestre (affiche avertissements) """
2022-09-07 17:40:40 +02:00
formsemestre : FormSemestre = FormSemestre . query . get_or_404 ( formsemestre_id )
2020-09-26 16:19:37 +02:00
H = [
2022-01-07 15:11:24 +01:00
html_sco_header . html_sem_header ( " Suppression du semestre " ) ,
2020-09-26 16:19:37 +02:00
""" <div class= " ue_warning " ><span>Attention !</span>
< p class = " help " > A n ' utiliser qu ' en cas d ' erreur lors de la saisie d ' une formation . Normalement ,
2022-09-07 17:40:40 +02:00
< b > un semestre ne doit jamais être supprimé < / b >
( on perd la mémoire des notes et de tous les événements liés à ce semestre ! ) .
< / p >
< p class = " help " > Tous les modules de ce semestre seront supprimés .
Ceci n ' est possible que si :
< / p >
< ol >
< li > aucune décision de jury n ' a été entrée dans ce semestre;</li>
< li > et aucun étudiant de ce semestre ne le compense avec un autre semestre . < / li >
< / ol >
< / div > """ ,
2020-09-26 16:19:37 +02:00
]
2021-11-12 22:17:46 +01:00
evals = sco_evaluation_db . do_evaluation_list_in_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
if evals :
H . append (
2022-09-07 17:40:40 +02:00
f """ <p class= " warning " >Attention: il y a { len ( evals ) } évaluations
dans ce semestre
( sa suppression entrainera l ' effacement définif des notes) !</p> " " "
2020-09-26 16:19:37 +02:00
)
submit_label = (
2022-09-07 17:40:40 +02:00
f " Confirmer la suppression (du semestre et des { len ( evals ) } évaluations !) "
2020-09-26 16:19:37 +02:00
)
else :
submit_label = " Confirmer la suppression du semestre "
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
( ( " formsemestre_id " , { " input_type " : " hidden " } ) , ) ,
2022-09-07 17:40:40 +02:00
initvalues = formsemestre . to_dict ( ) ,
2020-09-26 16:19:37 +02:00
submitlabel = submit_label ,
cancelbutton = " Annuler " ,
)
if tf [ 0 ] == 0 :
2023-06-01 19:48:52 +02:00
has_decisions , message = formsemestre_has_decisions_or_compensations (
formsemestre
)
if has_decisions :
2020-09-26 16:19:37 +02:00
H . append (
2023-06-01 19:48:52 +02:00
f """ <p><b>Ce semestre ne peut pas être supprimé !</b></p>
< p > il y a des décisions de jury ou des compensations par d ' autres semestres:
< / p >
< ul >
< li > { message } < / li >
< / ul >
"""
2020-09-26 16:19:37 +02:00
)
else :
H . append ( tf [ 1 ] )
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + html_sco_header . sco_footer ( )
2020-09-26 16:19:37 +02:00
elif tf [ 0 ] == - 1 : # cancel
2021-07-31 18:01:10 +02:00
return flask . redirect (
2022-09-07 17:40:40 +02:00
url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre_id ,
)
2021-02-07 09:10:26 +01:00
)
2020-09-26 16:19:37 +02:00
else :
2021-08-10 17:12:10 +02:00
return flask . redirect (
" formsemestre_delete2?formsemestre_id= " + str ( formsemestre_id )
)
2020-09-26 16:19:37 +02:00
2021-08-21 00:24:51 +02:00
def formsemestre_delete2 ( formsemestre_id , dialog_confirmed = False ) :
2020-09-26 16:19:37 +02:00
""" Delete a formsemestre (confirmation) """
# Confirmation dialog
if not dialog_confirmed :
2021-06-02 22:40:34 +02:00
return scu . confirm_dialog (
2020-09-26 16:19:37 +02:00
""" <h2>Vous voulez vraiment supprimer ce semestre ???</h2><p>(opération irréversible)</p> """ ,
dest_url = " " ,
cancel_url = " formsemestre_status?formsemestre_id= %s " % formsemestre_id ,
parameters = { " formsemestre_id " : formsemestre_id } ,
)
# Bon, s'il le faut...
2021-08-21 00:24:51 +02:00
do_formsemestre_delete ( formsemestre_id )
2023-04-15 10:50:20 +02:00
flash ( " Semestre supprimé ! " )
return flask . redirect ( scu . ScoURL ( ) )
2020-09-26 16:19:37 +02:00
2023-06-01 19:48:52 +02:00
def formsemestre_has_decisions_or_compensations (
formsemestre : FormSemestre ,
) - > tuple [ bool , str ] :
2023-02-27 17:45:20 +01:00
""" True if decision de jury (sem. UE, RCUE, année) émanant de ce semestre
ou compensation de ce semestre par d ' autres semestres
ou autorisations de passage .
2020-09-26 16:19:37 +02:00
"""
2023-02-27 17:45:20 +01:00
# Validations de semestre ou d'UEs
2023-06-01 19:48:52 +02:00
nb_validations = ScolarFormSemestreValidation . query . filter_by (
2023-02-27 17:45:20 +01:00
formsemestre_id = formsemestre . id
2023-06-01 19:48:52 +02:00
) . count ( )
if nb_validations :
return True , f " { nb_validations } validations de semestre ou d ' UE "
nb_validations = ScolarFormSemestreValidation . query . filter_by (
2023-02-27 17:45:20 +01:00
compense_formsemestre_id = formsemestre . id
2023-06-01 19:48:52 +02:00
) . count ( )
if nb_validations :
return True , f " { nb_validations } compensations utilisées dans d ' autres semestres "
2023-02-27 17:45:20 +01:00
# Autorisations d'inscription:
2023-06-01 19:48:52 +02:00
nb_validations = ScolarAutorisationInscription . query . filter_by (
2023-02-27 17:45:20 +01:00
origin_formsemestre_id = formsemestre . id
2023-06-01 19:48:52 +02:00
) . count ( )
if nb_validations :
return (
True ,
f " { nb_validations } autorisations d ' inscriptions émanant de ce semestre " ,
)
2023-02-27 17:45:20 +01:00
# Validations d'années BUT
2023-06-01 19:48:52 +02:00
nb_validations = ApcValidationAnnee . query . filter_by (
formsemestre_id = formsemestre . id
) . count ( )
if nb_validations :
return True , f " { nb_validations } validations d ' année BUT utilisant ce semestre "
2023-02-27 17:45:20 +01:00
# Validations de RCUEs
2023-06-01 19:48:52 +02:00
nb_validations = ApcValidationRCUE . query . filter_by (
formsemestre_id = formsemestre . id
) . count ( )
if nb_validations :
return True , f " { nb_validations } validations de RCUE utilisant ce semestre "
return False , " "
2020-09-26 16:19:37 +02:00
2021-08-21 00:24:51 +02:00
def do_formsemestre_delete ( formsemestre_id ) :
2020-09-26 16:19:37 +02:00
""" delete formsemestre, and all its moduleimpls.
No checks , no warnings : erase all !
"""
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
2021-07-19 19:53:01 +02:00
sco_cache . EvaluationCache . invalidate_sem ( formsemestre_id )
2020-09-26 16:19:37 +02:00
# --- Destruction des modules de ce semestre
2021-10-15 14:00:51 +02:00
mods = sco_moduleimpl . moduleimpl_list ( formsemestre_id = formsemestre_id )
2020-09-26 16:19:37 +02:00
for mod in mods :
# evaluations
2023-08-25 17:58:57 +02:00
evals = sco_evaluation_db . get_evaluation_dict (
2021-07-29 10:19:00 +02:00
args = { " moduleimpl_id " : mod [ " moduleimpl_id " ] }
2021-06-17 00:08:37 +02:00
)
2020-09-26 16:19:37 +02:00
for e in evals :
2021-02-03 22:00:41 +01:00
ndb . SimpleQuery (
2020-09-26 16:19:37 +02:00
" DELETE FROM notes_notes WHERE evaluation_id= %(evaluation_id)s " ,
e ,
)
2021-02-03 22:00:41 +01:00
ndb . SimpleQuery (
2020-09-26 16:19:37 +02:00
" DELETE FROM notes_notes_log WHERE evaluation_id= %(evaluation_id)s " ,
e ,
)
2021-02-03 22:00:41 +01:00
ndb . SimpleQuery (
2021-08-08 16:01:10 +02:00
" DELETE FROM notes_evaluation WHERE id= %(evaluation_id)s " ,
2020-09-26 16:19:37 +02:00
e ,
)
2021-01-17 22:31:28 +01:00
sco_moduleimpl . do_moduleimpl_delete (
2021-08-20 01:09:55 +02:00
mod [ " moduleimpl_id " ] , formsemestre_id = formsemestre_id
2020-09-26 16:19:37 +02:00
)
# --- Desinscription des etudiants
2021-02-03 22:00:41 +01:00
cursor = cnx . cursor ( cursor_factory = ndb . ScoDocCursor )
2020-09-26 16:19:37 +02:00
req = " DELETE FROM notes_formsemestre_inscription WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Suppression des evenements
req = " DELETE FROM scolar_events WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Suppression des appreciations
req = " DELETE FROM notes_appreciations WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Supression des validations (!!!)
req = " DELETE FROM scolar_formsemestre_validation WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Supression des references a ce semestre dans les compensations:
req = " UPDATE scolar_formsemestre_validation SET compense_formsemestre_id=NULL WHERE compense_formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Suppression des autorisations
req = " DELETE FROM scolar_autorisation_inscription WHERE origin_formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Suppression des coefs d'UE capitalisées
req = " DELETE FROM notes_formsemestre_uecoef WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Suppression des item du menu custom
req = " DELETE FROM notes_formsemestre_custommenu WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Suppression des formules
req = " DELETE FROM notes_formsemestre_ue_computation_expr WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Suppression des preferences
req = " DELETE FROM sco_prefs WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Suppression des groupes et partitions
2021-08-10 09:10:36 +02:00
req = """ DELETE FROM group_membership
WHERE group_id IN
( SELECT gm . group_id FROM group_membership gm , partition p , group_descr gd
WHERE gm . group_id = gd . id AND gd . partition_id = p . id
AND p . formsemestre_id = % ( formsemestre_id ) s )
"""
2020-09-26 16:19:37 +02:00
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
2021-08-10 09:10:36 +02:00
req = """ DELETE FROM group_descr
WHERE id IN
( SELECT gd . id FROM group_descr gd , partition p
WHERE gd . partition_id = p . id
AND p . formsemestre_id = % ( formsemestre_id ) s )
"""
2020-09-26 16:19:37 +02:00
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
req = " DELETE FROM partition WHERE formsemestre_id= %(formsemestre_id)s "
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
2021-08-10 09:10:36 +02:00
# --- Responsables
req = """ DELETE FROM notes_formsemestre_responsables
WHERE formsemestre_id = % ( formsemestre_id ) s """
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
# --- Etapes
req = """ DELETE FROM notes_formsemestre_etapes
WHERE formsemestre_id = % ( formsemestre_id ) s """
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
2023-02-02 19:51:50 +01:00
# --- Dispenses d'UE
req = """ DELETE FROM " dispenseUE " WHERE formsemestre_id= %(formsemestre_id)s """
cursor . execute ( req , { " formsemestre_id " : formsemestre_id } )
2020-09-26 16:19:37 +02:00
# --- Destruction du semestre
sco_formsemestre . _formsemestreEditor . delete ( cnx , formsemestre_id )
# news
2022-04-12 17:12:51 +02:00
ScolarNews . add (
typ = ScolarNews . NEWS_SEM ,
obj = formsemestre_id ,
2020-09-26 16:19:37 +02:00
text = " Suppression du semestre %(titre)s " % sem ,
2023-06-23 10:37:32 +02:00
max_frequency = 0 ,
2020-09-26 16:19:37 +02:00
)
# ---------------------------------------------------------------------------------------
2021-09-27 10:20:10 +02:00
def formsemestre_edit_options ( formsemestre_id ) :
2020-09-26 16:19:37 +02:00
""" dialog to change formsemestre options
( accessible par ScoImplement ou dir . etudes )
"""
log ( " formsemestre_edit_options " )
2021-07-31 18:01:10 +02:00
ok , err = sco_permissions_check . check_access_diretud ( formsemestre_id )
2020-09-26 16:19:37 +02:00
if not ok :
return err
2021-09-27 10:20:10 +02:00
return sco_preferences . SemPreferences ( formsemestre_id ) . edit ( categories = [ " bul " ] )
2020-09-26 16:19:37 +02:00
def formsemestre_change_publication_bul (
2021-09-27 10:20:10 +02:00
formsemestre_id , dialog_confirmed = False , redirect = True
2020-09-26 16:19:37 +02:00
) :
2020-12-16 01:34:08 +01:00
""" Change etat publication bulletins sur portail """
2021-07-31 18:01:10 +02:00
ok , err = sco_permissions_check . check_access_diretud ( formsemestre_id )
2020-09-26 16:19:37 +02:00
if not ok :
return err
2021-08-19 10:28:35 +02:00
sem = sco_formsemestre . get_formsemestre ( formsemestre_id )
2021-08-11 00:36:07 +02:00
etat = not sem [ " bul_hide_xml " ]
2020-09-26 16:19:37 +02:00
2021-09-27 10:20:10 +02:00
if not dialog_confirmed :
2020-09-26 16:19:37 +02:00
if etat :
msg = " non "
else :
msg = " "
2021-06-02 22:40:34 +02:00
return scu . confirm_dialog (
2020-09-26 16:19:37 +02:00
" <h2>Confirmer la %s publication des bulletins ?</h2> " % msg ,
2023-02-23 21:19:57 +01:00
help_msg = """ Il est parfois utile de désactiver la diffusion des bulletins,
2020-09-26 16:19:37 +02:00
par exemple pendant la tenue d ' un jury ou avant harmonisation des notes.
2022-10-02 23:43:29 +02:00
< br >
2020-09-26 16:19:37 +02:00
Ce réglage n ' a d ' effet que si votre établissement a interfacé ScoDoc et un portail étudiant .
""" ,
dest_url = " " ,
cancel_url = " formsemestre_status?formsemestre_id= %s " % formsemestre_id ,
parameters = { " bul_hide_xml " : etat , " formsemestre_id " : formsemestre_id } ,
)
args = { " formsemestre_id " : formsemestre_id , " bul_hide_xml " : etat }
2021-08-19 10:28:35 +02:00
sco_formsemestre . do_formsemestre_edit ( args )
2021-09-27 10:20:10 +02:00
if redirect :
2021-07-31 18:01:10 +02:00
return flask . redirect (
2020-09-26 16:19:37 +02:00
" formsemestre_status?formsemestre_id= %s " % formsemestre_id
)
2021-02-07 15:31:35 +01:00
return None
2020-09-26 16:19:37 +02:00
2021-09-27 10:20:10 +02:00
def formsemestre_edit_uecoefs ( formsemestre_id , err_ue_id = None ) :
2020-12-16 01:34:08 +01:00
""" Changement manuel des coefficients des UE capitalisées. """
2021-06-19 23:21:37 +02:00
2021-07-31 18:01:10 +02:00
ok , err = sco_permissions_check . check_access_diretud ( formsemestre_id )
2020-09-26 16:19:37 +02:00
if not ok :
return err
2021-07-29 10:19:00 +02:00
footer = html_sco_header . sco_footer ( )
2020-09-26 16:19:37 +02:00
help = """ <p class= " help " >
Seuls les modules ont un coefficient . Cependant , il est nécessaire d ' affecter un coefficient aux UE capitalisée pour pouvoir les prendre en compte dans la moyenne générale.
< / p >
< p class = " help " > ScoDoc calcule normalement le coefficient d ' une UE comme la somme des
coefficients des modules qui la composent .
< / p >
< p class = " help " > Dans certains cas , on n ' a pas les mêmes modules dans le semestre antérieur
( capitalisé ) et dans le semestre courant , et le coefficient d ' UE est alors variable.
Il est alors possible de forcer la valeur du coefficient d ' UE.
< / p >
< p class = " help " >
Indiquez " auto " ( ou laisser vide ) pour que ScoDoc calcule automatiquement le coefficient ,
ou bien entrez une valeur ( nombre réel ) .
< / p >
< p class = " help " > Dans le doute , si le mode auto n ' est pas applicable et que tous les étudiants sont inscrits aux mêmes modules de ce semestre, prenez comme coefficient la somme indiquée.
Sinon , référez vous au programme pédagogique . Les lignes en < font color = " red " > rouge < / font >
sont à changer .
< / p >
< p class = " warning " > Les coefficients indiqués ici ne s ' appliquent que pour le traitement des UE capitalisées.
< / p >
"""
2021-06-13 19:12:20 +02:00
H = [
2022-01-07 15:11:24 +01:00
html_sco_header . html_sem_header ( " Coefficients des UE du semestre " ) ,
2021-06-13 19:12:20 +02:00
help ,
]
2020-09-26 16:19:37 +02:00
#
2023-02-20 21:04:29 +01:00
ues , modimpls = _get_sem_ues_modimpls ( formsemestre_id )
2020-09-26 16:19:37 +02:00
for ue in ues :
ue [ " sum_coefs " ] = sum (
[
mod [ " module " ] [ " coefficient " ]
for mod in modimpls
if mod [ " module " ] [ " ue_id " ] == ue [ " ue_id " ]
]
)
2021-06-15 13:59:56 +02:00
cnx = ndb . GetDBConnexion ( )
2020-09-26 16:19:37 +02:00
initvalues = { " formsemestre_id " : formsemestre_id }
form = [ ( " formsemestre_id " , { " input_type " : " hidden " } ) ]
for ue in ues :
2021-01-17 22:31:28 +01:00
coefs = sco_formsemestre . formsemestre_uecoef_list (
2020-09-26 16:19:37 +02:00
cnx , args = { " formsemestre_id " : formsemestre_id , " ue_id " : ue [ " ue_id " ] }
)
if coefs :
2021-08-11 11:53:20 +02:00
initvalues [ " ue_ " + str ( ue [ " ue_id " ] ) ] = coefs [ 0 ] [ " coefficient " ]
2020-09-26 16:19:37 +02:00
else :
2021-08-11 11:53:20 +02:00
initvalues [ " ue_ " + str ( ue [ " ue_id " ] ) ] = " auto "
2020-09-26 16:19:37 +02:00
descr = {
" size " : 10 ,
" title " : ue [ " acronyme " ] ,
" explanation " : " somme coefs modules = %s " % ue [ " sum_coefs " ] ,
}
if ue [ " ue_id " ] == err_ue_id :
descr [ " dom_id " ] = " erroneous_ue "
2021-08-11 11:53:20 +02:00
form . append ( ( " ue_ " + str ( ue [ " ue_id " ] ) , descr ) )
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
form ,
submitlabel = " Changer les coefficients " ,
cancelbutton = " Annuler " ,
initvalues = initvalues ,
)
if tf [ 0 ] == 0 :
return " \n " . join ( H ) + tf [ 1 ] + footer
elif tf [ 0 ] == - 1 :
2023-01-14 00:05:39 +01:00
return redirect (
url_for (
" notes.formsemestre_editwithmodules " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre_id ,
)
)
2020-09-26 16:19:37 +02:00
else :
# change values
# 1- supprime les coef qui ne sont plus forcés
# 2- modifie ou cree les coefs
ue_deleted = [ ]
ue_modified = [ ]
msg = [ ]
for ue in ues :
2021-08-11 11:53:20 +02:00
val = tf [ 2 ] [ " ue_ " + str ( ue [ " ue_id " ] ) ]
2021-01-17 22:31:28 +01:00
coefs = sco_formsemestre . formsemestre_uecoef_list (
2020-09-26 16:19:37 +02:00
cnx , args = { " formsemestre_id " : formsemestre_id , " ue_id " : ue [ " ue_id " ] }
)
if val == " " or val == " auto " :
# supprime ce coef (il sera donc calculé automatiquement)
if coefs :
ue_deleted . append ( ue )
else :
try :
val = float ( val )
if ( not coefs ) or ( coefs [ 0 ] [ " coefficient " ] != val ) :
ue [ " coef " ] = val
ue_modified . append ( ue )
except :
ok = False
msg . append (
" valeur invalide ( %s ) pour le coefficient de l ' UE %s "
% ( val , ue [ " acronyme " ] )
)
if not ok :
return (
" \n " . join ( H )
+ " <p><ul><li> %s </li></ul></p> " % " </li><li> " . join ( msg )
+ tf [ 1 ]
+ footer
)
# apply modifications
for ue in ue_modified :
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 [ " ue_id " ] , ue [ " coef " ]
2020-09-26 16:19:37 +02:00
)
for ue in ue_deleted :
2021-01-17 22:31:28 +01:00
sco_formsemestre . do_formsemestre_uecoef_delete (
2021-08-19 10:28:35 +02:00
cnx , formsemestre_id , ue [ " ue_id " ]
2021-01-17 22:31:28 +01:00
)
2020-09-26 16:19:37 +02:00
if ue_modified or ue_deleted :
2022-10-01 15:34:39 +02:00
message = [ """ <h3>Modification effectuées</h3> """ ]
2020-09-26 16:19:37 +02:00
if ue_modified :
2022-10-01 15:34:39 +02:00
message . append ( """ <h4>Coefs modifiés dans les UE:<h4><ul> """ )
2020-09-26 16:19:37 +02:00
for ue in ue_modified :
2022-10-01 15:34:39 +02:00
message . append ( " <li> %(acronyme)s : %(coef)s </li> " % ue )
message . append ( " </ul> " )
2020-09-26 16:19:37 +02:00
if ue_deleted :
2022-10-01 15:34:39 +02:00
message . append ( """ <h4>Coefs supprimés dans les UE:<h4><ul> """ )
2020-09-26 16:19:37 +02:00
for ue in ue_deleted :
2022-10-01 15:34:39 +02:00
message . append ( " <li> %(acronyme)s </li> " % ue )
message . append ( " </ul> " )
2020-09-26 16:19:37 +02:00
else :
2022-10-01 15:34:39 +02:00
message = [ """ <h3>Aucune modification</h3> """ ]
2021-07-19 19:53:01 +02:00
sco_cache . invalidate_formsemestre (
formsemestre_id = formsemestre_id
2020-09-26 16:19:37 +02:00
) # > modif coef UE cap (modifs notes de _certains_ etudiants)
2022-10-01 15:34:39 +02:00
return f """ { html_sco_header . html_sem_header ( " Coefficients des UE du semestre " ) }
{ " " . join ( message ) }
< p > < a class = " stdlink " href = " { url_for( " notes . formsemestre_status " ,
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre_id )
} " >Revenir au tableau de bord</a>
< / p >
{ footer }
"""
2020-09-26 16:19:37 +02:00
2023-02-20 21:04:29 +01:00
def _get_sem_ues_modimpls ( formsemestre_id , modimpls = None ) :
""" Get liste des UE du semestre (à partir des moduleimpls)
( utilisé quand on ne peut pas construire nt et faire nt . get_ues_stat_dict ( ) )
"""
if modimpls is None :
modimpls = sco_moduleimpl . moduleimpl_list ( formsemestre_id = formsemestre_id )
uedict = { }
for modimpl in modimpls :
mod = sco_edit_module . module_list ( args = { " module_id " : modimpl [ " module_id " ] } ) [ 0 ]
modimpl [ " module " ] = mod
if not mod [ " ue_id " ] in uedict :
ue = sco_edit_ue . ue_list ( args = { " ue_id " : mod [ " ue_id " ] } ) [ 0 ]
uedict [ ue [ " ue_id " ] ] = ue
ues = list ( uedict . values ( ) )
ues . sort ( key = lambda u : u [ " numero " ] )
return ues , modimpls
2020-09-26 16:19:37 +02:00
# ----- identification externe des sessions (pour SOJA et autres logiciels)
2023-02-18 00:13:00 +01:00
def get_formsemestre_session_id ( sem , code_specialite , parcours ) :
2020-09-26 16:19:37 +02:00
""" Identifiant de session pour ce semestre
2021-12-04 21:04:09 +01:00
Obsolete : vooir FormSemestre . session_id ( ) #sco7
2020-09-26 16:19:37 +02:00
"""
2021-12-04 21:04:09 +01:00
imputation_dept = sco_preferences . get_preference (
2021-07-28 17:03:54 +02:00
" ImputationDept " , sem [ " formsemestre_id " ]
2021-06-13 23:37:14 +02:00
)
2021-12-04 21:04:09 +01:00
if not imputation_dept :
2022-07-11 21:39:30 +02:00
imputation_dept = sco_preferences . get_preference ( " DeptName " ) or " "
2021-12-04 21:04:09 +01:00
imputation_dept = imputation_dept . upper ( )
2020-09-26 16:19:37 +02:00
parcours_type = parcours . NAME
modalite = sem [ " modalite " ]
modalite = (
( modalite or " " ) . replace ( " FAP " , " FA " ) . replace ( " APP " , " FA " )
) # exception pour code Apprentissage
if sem [ " semestre_id " ] > 0 :
2021-02-04 20:02:44 +01:00
decale = scu . sem_decale_str ( sem )
2020-09-26 16:19:37 +02:00
semestre_id = " S %d " % sem [ " semestre_id " ] + decale
else :
2023-02-18 00:13:00 +01:00
semestre_id = code_specialite
2021-02-04 20:02:44 +01:00
annee_sco = str ( scu . annee_scolaire_debut ( sem [ " annee_debut " ] , sem [ " mois_debut_ord " ] ) )
2020-09-26 16:19:37 +02:00
2021-02-04 20:02:44 +01:00
return scu . sanitize_string (
2023-02-18 00:13:00 +01:00
" - " . join (
( imputation_dept , parcours_type , modalite , semestre_id or " " , annee_sco )
)
2020-09-26 16:19:37 +02:00
)