2020-09-26 16:19:37 +02:00
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
2023-12-31 23:04:06 +01:00
# Copyright (c) 1999 - 2024 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
2024-08-16 01:11:06 +02:00
from flask import flash , g , request , redirect , render_template , url_for
2021-08-11 00:36:07 +02:00
from flask_login import current_user
2024-02-26 17:20:36 +01:00
import sqlalchemy as sa
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 (
2024-06-18 01:21:33 +02:00
ApcValidationAnnee ,
ApcValidationRCUE ,
Evaluation ,
2024-09-04 21:01:03 +02:00
FormationModalite ,
2024-06-18 01:21:33 +02:00
FormSemestreUECoef ,
2023-02-27 17:45:20 +01:00
Module ,
ModuleImpl ,
2023-11-08 23:19:58 +01:00
ScoDocSiteConfig ,
2023-02-27 17:45:20 +01:00
ScolarAutorisationInscription ,
2024-06-18 01:21:33 +02:00
ScolarFormSemestreValidation ,
2023-02-27 17:45:20 +01:00
ScolarNews ,
2024-06-18 01:21:33 +02:00
UniteEns ,
2023-02-27 17:45:20 +01:00
)
2022-01-30 08:13:24 +01:00
from app . models . formations import Formation
2024-10-19 23:52:35 +02:00
from app . models . formsemestre import FormSemestre , FormSemestreEtape
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
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_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_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 """
2024-07-19 10:11:02 +02:00
return formation . acronyme
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 """
2024-08-24 08:06:46 +02:00
H = [ """ <h2>Mise en place d ' un semestre de formation</h2> """ ]
2021-09-27 10:20:10 +02:00
r = do_formsemestre_createwithmodules ( )
2024-08-24 08:06:46 +02:00
if not isinstance ( r , str ) :
2021-07-05 23:32:57 +02:00
return r # response redirect
2024-08-24 08:06:46 +02:00
H . append ( r )
return render_template (
" sco_page_dept.j2 " ,
title = " Création d ' un semestre " ,
content = " \n " . join ( H ) ,
javascripts = [ " libjs/AutoSuggest.js " , " js/formsemestre_edit.js " ] ,
cssstyles = [ " css/autosuggest_inquisitor.css " ] ,
)
2020-09-26 16:19:37 +02:00
2024-08-16 01:11:06 +02:00
def formsemestre_editwithmodules ( formsemestre_id : int ) :
2020-09-26 16:19:37 +02:00
""" Page modification semestre """
2024-08-16 01:11:06 +02:00
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
H = [ ]
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
)
2024-08-16 01:11:06 +02:00
return render_template (
" sco_page.j2 " ,
javascripts = [ " libjs/AutoSuggest.js " , " js/formsemestre_edit.js " ] ,
cssstyles = [ " css/autosuggest_inquisitor.css " ] ,
title = " Modification du semestre " ,
content = " <h2>Modification du semestre</h2> " + " \n " . join ( H ) ,
)
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 )
2023-09-29 21:17:31 +02:00
if not current_user . has_permission ( Permission . EditFormSemestre ) : # pas chef
2021-08-11 00:36:07 +02:00
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
2024-10-19 23:52:35 +02:00
RESP_FIELDS = [
2022-09-01 16:55:20 +02:00
" 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:
2023-09-29 21:17:31 +02:00
if not current_user . has_permission ( Permission . EditFormSemestre ) :
2020-09-26 16:19:37 +02:00
if not edit :
2023-09-29 21:17:31 +02:00
# il faut EditFormSemestre 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 ) :
2024-10-19 23:52:35 +02:00
initvalues [ RESP_FIELDS [ index ] ] = uid2display . get ( resp . id )
2023-11-13 12:16:10 +01:00
group_tous = formsemestre . get_default_group ( )
if group_tous :
initvalues [ " edt_promo_id " ] = group_tous . edt_id or " "
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 ( )
)
2023-12-15 01:07:08 +01:00
# Elimine les ressources et SAE sauf si déjà dans le semestre
modules = [
m
for m in modules
if ( m . module_type not in ( scu . ModuleType . RESSOURCE , scu . ModuleType . SAE ) )
or m . id in module_ids_set
]
2020-09-26 16:19:37 +02:00
# Pour regroupement des modules par semestres:
2024-09-04 21:01:03 +02:00
semestre_ids = sorted ( { mod . semestre_id for mod in modules } )
# Liste des modalités
modalites_abbrv_titres = {
modalite . modalite : modalite . titre
for modalite in FormationModalite . query . order_by ( FormationModalite . numero )
}
2020-09-26 16:19:37 +02:00
#
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 ,
2024-02-14 21:45:58 +01: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
)
2024-10-19 23:52:35 +02:00
for index , field in enumerate ( RESP_FIELDS )
2022-09-01 16:55:20 +02:00
] ,
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
2023-11-08 23:19:58 +01: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é " ,
2024-09-04 21:01:03 +02:00
" allowed_values " : modalites_abbrv_titres . keys ( ) ,
" labels " : modalites_abbrv_titres . values ( ) ,
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 ,
2024-02-14 21:45:58 +01:00
" explanation " : (
" en BUT, on ne peut pas modifier le semestre après création "
if is_apc
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
} ,
) ,
2024-08-11 23:24:40 +02:00
(
" capacite_accueil " ,
{
" title " : " Capacité d ' accueil " ,
" size " : 4 ,
2024-08-12 14:40:35 +02:00
" explanation " : " nombre max d ' inscrits (hors démissionnaires). Laisser vide si pas de limite. " ,
2024-08-11 23:24:40 +02:00
" type " : " int " ,
" allow_null " : True ,
} ,
) ,
]
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
2024-08-11 23:24:40 +02:00
# 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)
2020-09-26 16:19:37 +02:00
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 ,
2024-06-09 15:18:03 +02:00
" title " : " Element(s) Apogée sem.: " ,
2024-06-18 01:21:33 +02:00
" explanation " : """ associé(s) au résultat du semestre (ex: VRTW1).
Inutile en BUT . Séparés par des virgules . """ ,
" allow_null " : (
not sco_preferences . get_preference ( " always_require_apo_sem_codes " )
or ( formsemestre and formsemestre . modalite == " EXT " )
or ( formsemestre and formsemestre . formation . is_apc ( ) )
) ,
2020-09-26 16:19:37 +02:00
} ,
)
)
modform . append (
(
" elt_annee_apo " ,
{
" size " : 32 ,
2024-06-09 15:18:03 +02:00
" title " : " Element(s) Apogée anné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
} ,
)
)
2024-06-24 03:37:40 +02:00
modform . append (
(
" elt_passage_apo " ,
{
" size " : 32 ,
" title " : " Element(s) Apogée passage: " ,
" explanation " : " associé(s) au passage. Séparés par des virgules. " ,
" allow_null " : True , # toujours optionnel car rarement utilisé
} ,
)
)
2023-11-08 23:19:58 +01:00
if ScoDocSiteConfig . get ( " edt_ics_path " ) :
modform . append (
(
" edt_id " ,
{
" size " : 32 ,
" title " : " Identifiant EDT " ,
" explanation " : " optionnel, identifiant sur le logiciel emploi du temps (par défaut, utilise la première étape Apogée). " ,
" allow_null " : True ,
} ,
)
)
2023-11-13 12:16:10 +01:00
modform . append (
(
" edt_promo_id " ,
{
" size " : 32 ,
" title " : " Identifiant EDT promo " ,
" explanation " : """ optionnel, identifiant du groupe " tous "
( promotion complète ) dans l ' emploi du temps. " " " ,
" allow_null " : True ,
} ,
)
)
2020-09-26 16:19:37 +02:00
if edit :
2022-05-22 03:26:39 +02:00
formtit = f """
2023-11-08 23:19:58 +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 >
2023-11-12 19:58:55 +01:00
< p > < a class = " stdlink " href = " { url_for( " notes . formsemestre_edit_modimpls_codes " ,
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre . id )
} " >Modifier les codes Apogée et emploi du temps des modules</a>
< / p >
2024-08-11 21:39:43 +02:00
< p > < a class = " stdlink " href = " { url_for( " notes . edit_formsemestre_description " ,
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre . id )
} " >Éditer la description externe du semestre</a>
< / p >
2023-11-08 23:19:58 +01:00
< h3 > Sélectionner les modules , leurs responsables et les étudiants
2022-05-22 03:26:39 +02:00
à 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 " : [ " " ] ,
} ,
) ,
]
2023-09-29 21:17:31 +02:00
if current_user . has_permission ( Permission . EditFormSemestre ) :
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 " : " " ,
2023-11-08 23:19:58 +01:00
" explanation " : """ Autoriser tous les enseignants associés
2022-02-28 17:57:12 +01:00
à 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 " ] ,
2024-03-01 12:03:19 +01:00
" explanation " : " publier le bulletin sur la passerelle étudiants " ,
2020-09-26 16:19:37 +02:00
" labels " : [ " " ] ,
} ,
) ,
2021-09-16 22:24:08 +02:00
(
" block_moyennes " ,
{
" input_type " : " boolcheckbox " ,
" title " : " Bloquer moyennes " ,
2024-01-31 23:07:03 +01:00
" explanation " : " empêcher le calcul des moyennes d ' UE et générale (en BUT, empèche sa prise en compte dans les jurys annuels) " ,
2021-09-16 22:24:08 +02:00
} ,
) ,
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 }
2023-11-08 23:19:58 +01:00
Pas de parcours :
< a class = " stdlink " href = " { url_for( ' notes.ue_table ' ,
2022-05-22 03:26:39 +02:00
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 ,
2024-10-19 23:52:35 +02:00
" title " : f """ { 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 :
2024-03-24 09:17:01 +01:00
# convert and check dates
tf [ 2 ] [ " date_debut " ] = scu . convert_fr_date ( tf [ 2 ] [ " date_debut " ] )
tf [ 2 ] [ " date_fin " ] = scu . convert_fr_date ( tf [ 2 ] [ " date_fin " ] )
if tf [ 2 ] [ " date_debut " ] > tf [ 2 ] [ " date_fin " ] :
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 (
2024-03-24 09:17:01 +01:00
tf [ 2 ] [ " etape_apo " + str ( n ) ] for n in range ( 0 , scu . EDIT_NB_ETAPES + 1 )
2022-09-30 23:29:06 +02:00
)
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
2024-08-12 14:40:35 +02:00
# check capacité accueil si indiquée
if edit and isinstance ( tf [ 2 ] [ " capacite_accueil " ] , int ) :
new_capacite_accueil = tf [ 2 ] [ " capacite_accueil " ]
inscriptions = formsemestre . get_inscrits ( etats = { scu . INSCRIT , scu . DEF } )
if len ( inscriptions ) > new_capacite_accueil :
msg = f """ <ul class= " tf-msg " ><li class= " tf-msg " >Capacité d ' accueil insuffisante
( il y a { len ( inscriptions ) } inscrits non démissionaires ) < / li > < / ul > """
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= " {
2023-11-08 23:19:58 +01: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
)
2024-10-19 23:52:35 +02:00
return redirect ( url_for ( " notes.index_html " , scodoc_dept = g . scodoc_dept ) )
# Edition ou modification du semestre
tf [ 2 ] [ " gestion_compensation " ] = bool ( tf [ 2 ] [ " gestion_compensation_lst " ] )
tf [ 2 ] [ " gestion_semestrielle " ] = bool ( tf [ 2 ] [ " gestion_semestrielle_lst " ] )
tf [ 2 ] [ " bul_hide_xml " ] = not bool ( tf [ 2 ] [ " bul_publish_xml_lst " ] )
_remap_resp_modimpls ( tf [ 2 ] )
2022-05-22 03:26:39 +02:00
if " parcours " in tf [ 2 ] :
2024-10-19 23:52:35 +02:00
tf [ 2 ] [ " 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 " ]
]
2024-10-19 23:52:35 +02: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 " ] ]
_formsemestre_check_ue_bonus_unicity ( module_ids_checked )
if not edit :
if is_apc :
_formsemestre_check_module_list ( module_ids_checked , tf [ 2 ] [ " semestre_id " ] )
# création du semestre
formsemestre = FormSemestre . create_formsemestre ( tf [ 2 ] )
# création des modules
for module_id in module_ids_checked :
modargs = {
" module_id " : module_id ,
" formsemestre_id " : formsemestre . id ,
" responsable_id " : tf [ 2 ] [ f " MI { module_id } " ] ,
}
_ = ModuleImpl . create_from_dict ( modargs )
else :
# Modification du semestre:
# on doit creer les modules nouvellement selectionnés
# 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
]
if is_apc :
_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
]
#
formsemestre . from_dict ( tf [ 2 ] )
sco_cache . invalidate_formsemestre ( formsemestre . id )
#
msg = [ ]
for module_id in module_ids_tocreate :
modargs = {
" module_id " : module_id ,
" formsemestre_id " : formsemestre . id ,
" responsable_id " : tf [ 2 ] [ " MI " + str ( module_id ) ] ,
}
modimpl = ModuleImpl . create_from_dict ( modargs )
assert modimpl . module_id == module_id
mod = modimpl . module
msg + = [ f """ création de { mod . code or " ? " } ( { mod . titre or " ? " } ) """ ]
# INSCRIPTIONS DES ETUDIANTS
group_id = tf [ 2 ] [ f " { module_id } !group_id " ]
log ( f """ inscription module: { module_id } !group_id = ' { group_id } ' """ )
if group_id :
etudids = [ x [ " etudid " ] for x in sco_groups . get_group_members ( group_id ) ]
log (
f """ inscription module:module_id= { module_id } ,moduleimpl_id= {
modimpl . id } : { etudids } """
)
sco_moduleimpl . do_moduleimpl_inscrit_etuds (
modimpl . id ,
formsemestre . id ,
etudids ,
)
msg + = [
f """ inscription de { len ( etudids ) } étudiants au module {
mod . code or " (module sans code) " } """
]
else :
log (
f """ inscription module:module_id= { module_id } ,moduleimpl_id= {
modimpl . id } : aucun etudiant inscrit """
)
#
ok , diag = formsemestre_delete_moduleimpls ( formsemestre . id , module_ids_todelete )
msg + = diag
for module_id in module_ids_toedit :
moduleimpl_id = sco_moduleimpl . moduleimpl_list (
formsemestre_id = formsemestre . id , module_id = module_id
) [ 0 ] [ " moduleimpl_id " ]
modargs = {
" moduleimpl_id " : moduleimpl_id ,
" module_id " : module_id ,
" formsemestre_id " : formsemestre . id ,
" responsable_id " : tf [ 2 ] [ " MI " + str ( module_id ) ] ,
}
sco_moduleimpl . do_moduleimpl_edit ( modargs , formsemestre_id = formsemestre . id )
# --- Etapes
_set_apo_etapes ( formsemestre , tf [ 2 ] , etapes )
# --- id edt du groupe par défault
2023-11-16 11:08:48 +01:00
if " edt_promo_id " in tf [ 2 ] :
group_tous = formsemestre . get_default_group ( )
if group_tous :
group_tous . edt_id = tf [ 2 ] [ " edt_promo_id " ]
db . session . add ( group_tous )
2023-11-13 12:16:10 +01:00
2022-05-22 03:26:39 +02:00
db . session . add ( formsemestre )
db . session . commit ( )
2023-11-13 12:16:10 +01:00
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 :
2024-10-19 23:52:35 +02:00
log ( f """ formsemestre_edit: { formsemestre } """ )
2022-05-22 03:26:39 +02:00
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 >
2023-11-08 23:19:58 +01:00
{ " <p>Modification effectuée</p> " if ok
2022-10-01 15:34:39 +02:00
else " <p>Modules non modifiés</p> "
}
< a class = " stdlink " href = " {
2023-11-08 23:19:58 +01:00
url_for ( ' notes.formsemestre_status ' ,
2022-10-01 15:34:39 +02:00
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre . id )
} " >retour au tableau de bord</a>
"""
2024-10-19 23:52:35 +02:00
flash ( " Semestre modifié " )
2022-05-22 03:26:39 +02:00
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 ,
2024-10-19 23:52:35 +02:00
check_parcours = 0 ,
2022-05-22 03:26:39 +02:00
)
)
2024-10-19 23:52:35 +02:00
flash ( " Nouveau semestre créé " )
return flask . redirect (
url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre . id ,
)
)
def _remap_resp_modimpls ( args : dict ) :
" remap les identifiants de responsables de modules "
for field in RESP_FIELDS :
resp = User . get_user_from_nomplogin ( args [ field ] )
args [ field ] = resp . id if resp else - 1
args [ " responsables " ] = [ ]
for field in RESP_FIELDS :
if args [ field ] :
args [ " responsables " ] . append ( args [ field ] )
for module_id in args [ " tf-checked " ] :
mod_resp = User . get_user_from_nomplogin ( args [ module_id ] )
if mod_resp is None :
# Si un module n'a pas de responsable (ou inconnu),
# l'affecte au 1er directeur des etudes:
mod_resp_id = args [ " responsable_id " ]
else :
mod_resp_id = mod_resp . id
args [ module_id ] = mod_resp_id
def _set_apo_etapes ( formsemestre : FormSemestre , args : dict , etapes : list [ str ] ) :
""" Affecte les étapes Apo du semestre,
à partir de args [ " etape_apo<n> " ] et args [ " vdi_apo<n>]
"""
# menus => case supplementaire pour saisie manuelle, indicée 0
start_i = 0 if etapes else 1
apo_etapes_vdi = [ ]
for n in range ( start_i , scu . EDIT_NB_ETAPES + 1 ) :
apo_etapes_vdi . append (
ApoEtapeVDI ( etape = args [ " etape_apo " + str ( n ) ] , vdi = args [ " vdi_apo " + str ( n ) ] )
)
# uniques:
apo_etapes_vdi_uniq = { str ( e ) : e for e in apo_etapes_vdi if str ( e ) } . values ( )
formsemestre . etapes = [ ]
db . session . add ( formsemestre )
db . session . flush ( )
formsemestre . etapes = [
FormSemestreEtape . create_from_apovdi ( formsemestre . id , etape_vdi )
for etape_vdi in apo_etapes_vdi_uniq
]
db . session . add ( formsemestre )
db . session . flush ( )
log ( f " setting etapes: { formsemestre } : { formsemestre . etapes } " )
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 = " {
2024-02-26 17:20:36 +01:00
url_for ( " notes.moduleimpl_status " ,
scodoc_dept = g . scodoc_dept , moduleimpl_id = modimpl . id )
2022-09-14 10:35:51 +02:00
} " 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 = [
2024-08-16 01:11:06 +02:00
""" <p class= " help " >Cette opération duplique un semestre:
on reprend les mêmes modules et responsables .
Aucun étudiant n ' est inscrit.</p> " " " ,
2020-09-26 16:19:37 +02:00
]
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 :
2024-08-16 01:11:06 +02:00
return render_template (
" sco_page.j2 " ,
javascripts = [ " libjs/AutoSuggest.js " ] ,
cssstyles = [ " css/autosuggest_inquisitor.css " ] ,
title = " Copie du semestre " ,
content = " " . join ( H ) + msg + tf [ 1 ] ,
)
2020-09-26 16:19:37 +02:00
elif tf [ 0 ] == - 1 : # cancel
2021-07-31 18:01:10 +02:00
return flask . redirect (
2024-02-26 17:20:36 +01:00
url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre_id ,
)
2020-09-26 16:19:37 +02:00
)
else :
2024-02-04 23:08:08 +01:00
resp = User . get_user_from_nomplogin ( tf [ 2 ] [ " responsable_id " ] )
if not resp :
raise ScoValueError ( " id responsable invalide " )
2020-09-26 16:19:37 +02:00
new_formsemestre_id = do_formsemestre_clone (
formsemestre_id ,
2024-06-18 01:21:33 +02:00
resp ,
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 ,
2024-06-18 01:21:33 +02:00
responsable : User , # new resp.
2020-09-26 16:19:37 +02:00
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.
2024-08-11 21:39:43 +02:00
Clone description .
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
)
2020-09-26 16:19:37 +02:00
# 1- create sem
2024-06-18 01:21:33 +02:00
args = formsemestre_orig . to_dict ( )
2020-09-26 16:19:37 +02:00
del args [ " formsemestre_id " ]
2024-06-18 01:21:33 +02:00
del args [ " id " ]
del args [ " parcours " ] # copiés ensuite
args [ " responsables " ] = [ responsable ]
2020-09-26 16:19:37 +02:00
args [ " date_debut " ] = date_debut
args [ " date_fin " ] = date_fin
args [ " etat " ] = 1 # non verrouillé
2024-06-18 01:21:33 +02:00
formsemestre = FormSemestre . create_formsemestre ( args )
log ( f " created formsemestre { formsemestre } " )
2020-09-26 16:19:37 +02:00
# 2- create moduleimpls
2024-02-03 23:25:05 +01:00
modimpl_orig : ModuleImpl
for modimpl_orig in formsemestre_orig . modimpls :
2024-06-18 01:21:33 +02:00
assert isinstance ( modimpl_orig , ModuleImpl )
assert isinstance ( modimpl_orig . id , int )
log ( f " cloning { modimpl_orig } " )
2024-02-03 23:25:05 +01:00
args = modimpl_orig . to_dict ( with_module = False )
2024-06-18 01:21:33 +02:00
args [ " formsemestre_id " ] = formsemestre . id
2024-02-03 23:25:05 +01:00
modimpl_new = ModuleImpl . create_from_dict ( args )
2024-06-18 01:21:33 +02:00
log ( f " created ModuleImpl from { args } " )
2024-02-03 23:25:05 +01:00
db . session . flush ( )
# copy enseignants
for ens in modimpl_orig . enseignants :
modimpl_new . enseignants . append ( ens )
db . session . add ( modimpl_new )
2024-06-18 01:21:33 +02:00
db . session . flush ( )
log ( f " new moduleimpl.id = { modimpl_new . id } " )
2020-09-26 16:19:37 +02:00
# optionally, copy evaluations
if clone_evaluations :
2024-06-18 01:21:33 +02:00
e : Evaluation
2024-02-03 23:25:05 +01:00
for e in Evaluation . query . filter_by ( moduleimpl_id = modimpl_orig . id ) :
2024-06-18 01:21:33 +02:00
log ( f " cloning evaluation { e . id } " )
2021-12-16 22:54:24 +01:00
# copie en enlevant la date
2024-06-18 01:21:33 +02:00
args = dict ( e . __dict__ )
args . pop ( " _sa_instance_state " )
args . pop ( " id " )
2024-07-15 21:22:21 +02:00
args . pop ( " date_debut " , None )
args . pop ( " date_fin " , None )
2024-06-18 01:21:33 +02:00
args [ " moduleimpl_id " ] = modimpl_new . id
new_eval = Evaluation ( * * args )
db . session . add ( new_eval )
db . session . commit ( )
2021-12-16 22:54:24 +01:00
# Copie les poids APC de l'évaluation
new_eval . set_ue_poids_dict ( e . get_ue_poids_dict ( ) )
db . session . commit ( )
2024-07-15 21:22:21 +02:00
if clone_evaluations :
flash (
" Attention: les évaluations n ' ont plus de dates: n ' oubliez pas de les indiquer "
)
2020-09-26 16:19:37 +02:00
# 3- copy uecoefs
2024-06-18 01:21:33 +02:00
for ue_coef in FormSemestreUECoef . query . filter_by (
formsemestre_id = formsemestre_orig . id
) :
new_ue_coef = FormSemestreUECoef (
formsemestre_id = formsemestre . id ,
ue_id = ue_coef . ue_id ,
coefficient = ue_coef . coefficient ,
)
db . session . add ( new_ue_coef )
db . session . flush ( )
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 :
2024-06-18 01:21:33 +02:00
prefs . base_prefs . set ( formsemestre . id , pname , pvalue )
2021-07-12 10:51:45 +02:00
except ValueError :
log (
2024-06-18 01:21:33 +02:00
f """ do_formsemestre_clone: ignoring old preference {
pname } = { pvalue } for { formsemestre } """
2021-07-12 10:51:45 +02:00
)
2020-09-26 16:19:37 +02:00
2024-02-27 21:51:43 +01:00
# 5- Copie les parcours
2023-01-24 00:35:15 +01:00
formsemestre . parcours = formsemestre_orig . parcours
2024-08-11 21:39:43 +02:00
# 6- Copy description
2024-08-24 09:23:35 +02:00
if formsemestre_orig . description :
formsemestre . description = formsemestre_orig . description . clone ( )
2024-08-11 21:39:43 +02:00
2023-01-24 00:35:15 +01:00
db . session . add ( formsemestre )
db . session . commit ( )
2024-08-11 21:39:43 +02:00
# 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 (
2024-06-18 01:21:33 +02:00
orig_formsemestre_id , formsemestre . id
2021-10-12 16:05:50 +02:00
)
2020-09-26 16:19:37 +02:00
2024-06-18 01:21:33 +02:00
return formsemestre . id
2020-09-26 16:19:37 +02:00
2024-02-26 17:20:36 +01:00
def formsemestre_delete ( formsemestre_id : int ) - > str | flask . Response :
2020-09-26 16:19:37 +02:00
""" Delete a formsemestre (affiche avertissements) """
2024-02-26 17:20:36 +01:00
formsemestre : FormSemestre = FormSemestre . get_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
H = [
2024-08-16 01:11:06 +02:00
""" <h2>Suppression du semestre</h2>
< div class = " ue_warning " > < span > Attention ! < / span >
2020-09-26 16:19:37 +02:00
< p class = " help " > A n ' utiliser qu ' en cas d ' erreur lors de la saisie d ' une formation . Normalement ,
2023-11-08 23:19:58 +01:00
< b > un semestre ne doit jamais être supprimé < / b >
2022-09-07 17:40:40 +02:00
( on perd la mémoire des notes et de tous les événements liés à ce semestre ! ) .
< / p >
2023-11-08 23:19:58 +01:00
< p class = " help " > Tous les modules de ce semestre seront supprimés .
2022-09-07 17:40:40 +02:00
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
]
2024-02-26 17:20:36 +01:00
evaluations = (
Evaluation . query . join ( ModuleImpl )
. filter_by ( formsemestre_id = formsemestre . id )
. all ( )
)
if evaluations :
2020-09-26 16:19:37 +02:00
H . append (
2024-02-26 17:20:36 +01:00
f """ <p class= " warning " >Attention: il y a { len ( evaluations ) } évaluations
2022-09-07 17:40:40 +02:00
dans ce semestre
( sa suppression entrainera l ' effacement définif des notes) !</p> " " "
2020-09-26 16:19:37 +02:00
)
2024-02-26 17:20:36 +01:00
submit_label = f " Confirmer la suppression (du semestre et des { len ( evaluations ) } é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 ] )
2024-08-16 01:11:06 +02:00
return render_template (
" sco_page.j2 " , title = " Suppression du semestre " , content = " \n " . join ( H )
)
2024-02-26 17:20:36 +01:00
if 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
)
2024-02-26 17:20:36 +01: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) """
2024-04-08 18:56:43 +02:00
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
2020-09-26 16:19:37 +02:00
# Confirmation dialog
if not dialog_confirmed :
2021-06-02 22:40:34 +02:00
return scu . confirm_dialog (
2024-04-08 18:56:43 +02:00
""" <h2>Vous voulez vraiment supprimer ce semestre ???</h2>
< p > ( opération irréversible ) < / p >
""" ,
2020-09-26 16:19:37 +02:00
dest_url = " " ,
2024-04-08 18:56:43 +02:00
cancel_url = url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre . id ,
) ,
parameters = { " formsemestre_id " : formsemestre . id } ,
2020-09-26 16:19:37 +02:00
)
# Bon, s'il le faut...
2024-04-08 18:56:43 +02:00
do_formsemestre_delete ( formsemestre . id )
2023-04-15 10:50:20 +02:00
flash ( " Semestre supprimé ! " )
2024-04-08 18:56:43 +02:00
return flask . redirect ( url_for ( " scolar.index_html " , scodoc_dept = g . scodoc_dept ) )
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
2024-02-26 17:20:36 +01:00
def do_formsemestre_delete ( formsemestre_id : int ) :
2020-09-26 16:19:37 +02:00
""" delete formsemestre, and all its moduleimpls.
No checks , no warnings : erase all !
"""
2024-02-26 17:20:36 +01:00
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
sco_cache . EvaluationCache . invalidate_sem ( formsemestre . id )
titre_sem = formsemestre . titre_annee ( )
2020-09-26 16:19:37 +02:00
# --- Destruction des modules de ce semestre
2024-02-26 17:20:36 +01:00
for modimpl in formsemestre . modimpls :
2020-09-26 16:19:37 +02:00
# evaluations
2024-02-26 17:20:36 +01:00
for e in modimpl . evaluations :
db . session . execute (
sa . text (
""" DELETE FROM notes_notes WHERE evaluation_id=:evaluation_id """
) ,
{ " evaluation_id " : e . id } ,
2020-09-26 16:19:37 +02:00
)
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
""" DELETE FROM notes_notes_log WHERE evaluation_id=:evaluation_id """
) ,
{ " evaluation_id " : e . id } ,
2020-09-26 16:19:37 +02:00
)
2024-02-26 17:20:36 +01:00
db . session . delete ( e )
db . session . delete ( modimpl )
2020-09-26 16:19:37 +02:00
# --- Desinscription des etudiants
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM notes_formsemestre_inscription WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Suppression des evenements
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text ( " DELETE FROM scolar_events WHERE formsemestre_id=:formsemestre_id " ) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Suppression des appreciations
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM notes_appreciations WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Supression des validations (!!!)
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM scolar_formsemestre_validation WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Supression des references a ce semestre dans les compensations:
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
""" UPDATE scolar_formsemestre_validation
SET compense_formsemestre_id = NULL
WHERE compense_formsemestre_id = : formsemestre_id """
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Suppression des autorisations
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM scolar_autorisation_inscription WHERE origin_formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Suppression des coefs d'UE capitalisées
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM notes_formsemestre_uecoef WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Suppression des item du menu custom
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM notes_formsemestre_custommenu WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Suppression des formules
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM notes_formsemestre_ue_computation_expr WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Suppression des preferences
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text ( " DELETE FROM sco_prefs WHERE formsemestre_id=:formsemestre_id " ) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Suppression des groupes et partitions
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
"""
DELETE FROM group_membership
2023-11-08 23:19:58 +01:00
WHERE group_id IN
2021-08-10 09:10:36 +02:00
( SELECT gm . group_id FROM group_membership gm , partition p , group_descr gd
2023-11-08 23:19:58 +01:00
WHERE gm . group_id = gd . id AND gd . partition_id = p . id
2024-02-26 17:20:36 +01:00
AND p . formsemestre_id = : formsemestre_id )
2021-08-10 09:10:36 +02:00
"""
2024-02-26 17:20:36 +01:00
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
db . session . execute (
sa . text (
"""
DELETE FROM group_descr
2023-11-08 23:19:58 +01:00
WHERE id IN
( SELECT gd . id FROM group_descr gd , partition p
WHERE gd . partition_id = p . id
2024-02-26 17:20:36 +01:00
AND p . formsemestre_id = : formsemestre_id )
2021-08-10 09:10:36 +02:00
"""
2024-02-26 17:20:36 +01:00
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
db . session . execute (
sa . text ( " DELETE FROM partition WHERE formsemestre_id=:formsemestre_id " ) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2021-08-10 09:10:36 +02:00
# --- Responsables
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM notes_formsemestre_responsables WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2021-08-10 09:10:36 +02:00
# --- Etapes
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text (
" DELETE FROM notes_formsemestre_etapes WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
# --- SemSets
db . session . execute (
sa . text (
" DELETE FROM notes_semset_formsemestre WHERE formsemestre_id=:formsemestre_id "
) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2023-02-02 19:51:50 +01:00
# --- Dispenses d'UE
2024-02-26 17:20:36 +01:00
db . session . execute (
sa . text ( """ DELETE FROM " dispenseUE " WHERE formsemestre_id=:formsemestre_id """ ) ,
{ " formsemestre_id " : formsemestre_id } ,
)
2020-09-26 16:19:37 +02:00
# --- Destruction du semestre
2024-02-26 17:20:36 +01:00
db . session . delete ( formsemestre )
2020-09-26 16:19:37 +02:00
# news
2022-04-12 17:12:51 +02:00
ScolarNews . add (
typ = ScolarNews . NEWS_SEM ,
obj = formsemestre_id ,
2024-02-26 17:20:36 +01:00
text = f " Suppression du semestre { titre_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
2023-09-29 21:17:31 +02:00
( accessible par EditFormSemestre ou dir . etudes )
2020-09-26 16:19:37 +02:00
"""
2024-10-19 23:52:35 +02:00
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
ok , err = sco_permissions_check . check_access_diretud ( formsemestre )
2020-09-26 16:19:37 +02:00
if not ok :
return err
2024-01-26 16:14:08 +01:00
return sco_preferences . SemPreferences ( formsemestre_id ) . edit (
categories = [ " bul " , " bul_but_pdf " ]
)
2020-09-26 16:19:37 +02:00
2024-10-19 23:52:35 +02:00
def formsemestre_change_publication_bul ( formsemestre_id , dialog_confirmed = False ) :
""" Change état publication bulletins sur portail """
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
ok , err = sco_permissions_check . check_access_diretud ( formsemestre )
2020-09-26 16:19:37 +02:00
if not ok :
return err
2024-10-19 23:52:35 +02:00
etat = not formsemestre . bul_hide_xml
2020-09-26 16:19:37 +02:00
2024-10-19 23:52:35 +02:00
status_url = url_for (
" notes.formsemestre_status " ,
scodoc_dept = g . scodoc_dept ,
formsemestre_id = formsemestre . id ,
)
2021-09-27 10:20:10 +02:00
if not dialog_confirmed :
2024-10-19 23:52:35 +02:00
msg = " non " if etat else " "
2021-06-02 22:40:34 +02:00
return scu . confirm_dialog (
2024-10-19 23:52:35 +02:00
f " <h2>Confirmer la { msg } publication des bulletins ?</h2> " ,
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 >
2024-10-19 23:52:35 +02:00
Ce réglage n ' a d ' effet que si votre établissement a interfacé ScoDoc avec
une passerelle étudiant .
2020-09-26 16:19:37 +02:00
""" ,
dest_url = " " ,
2024-10-19 23:52:35 +02:00
cancel_url = status_url ,
2020-09-26 16:19:37 +02:00
parameters = { " bul_hide_xml " : etat , " formsemestre_id " : formsemestre_id } ,
)
2024-10-19 23:52:35 +02:00
formsemestre . bul_hide_xml = etat
db . session . add ( formsemestre )
db . session . commit ( )
log ( f " formsemestre_change_publication_bul: { formsemestre } -> { etat } " )
return flask . redirect ( status_url )
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. """
2024-02-14 21:45:58 +01:00
formsemestre = FormSemestre . get_formsemestre ( formsemestre_id )
2024-10-19 23:52:35 +02:00
ok , err = sco_permissions_check . check_access_diretud ( formsemestre )
2020-09-26 16:19:37 +02:00
if not ok :
return err
2024-02-14 21:45:58 +01:00
help_msg = """ <p class= " help " >
2020-09-26 16:19:37 +02:00
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 >
2023-11-08 23:19:58 +01:00
< 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.
2020-09-26 16:19:37 +02:00
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 = [
2024-02-14 21:45:58 +01:00
help_msg ,
2021-06-13 19:12:20 +02:00
]
2020-09-26 16:19:37 +02:00
#
2024-02-14 21:45:58 +01:00
ues , modimpls = _get_sem_ues_modimpls ( formsemestre )
sum_coefs_by_ue_id = { }
2020-09-26 16:19:37 +02:00
for ue in ues :
2024-02-14 21:45:58 +01:00
sum_coefs_by_ue_id [ ue . id ] = sum (
2024-02-21 17:51:54 +01:00
modimpl . module . coefficient or 0.0
2024-02-14 21:45:58 +01:00
for modimpl in modimpls
if modimpl . module . ue_id == ue . id
2020-09-26 16:19:37 +02:00
)
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 (
2024-02-14 21:45:58 +01:00
cnx , args = { " formsemestre_id " : formsemestre_id , " ue_id " : ue . id }
2020-09-26 16:19:37 +02:00
)
if coefs :
2024-02-14 21:45:58 +01:00
initvalues [ " ue_ " + str ( ue . id ) ] = coefs [ 0 ] [ " coefficient " ]
2020-09-26 16:19:37 +02:00
else :
2024-02-14 21:45:58 +01:00
initvalues [ " ue_ " + str ( ue . id ) ] = " auto "
2020-09-26 16:19:37 +02:00
descr = {
" size " : 10 ,
2024-02-14 21:45:58 +01:00
" title " : ue . acronyme ,
" explanation " : f " somme coefs modules = { sum_coefs_by_ue_id [ ue . id ] } " ,
2020-09-26 16:19:37 +02:00
}
2024-02-14 21:45:58 +01:00
if ue . id == err_ue_id :
2020-09-26 16:19:37 +02:00
descr [ " dom_id " ] = " erroneous_ue "
2024-02-14 21:45:58 +01:00
form . append ( ( " ue_ " + str ( 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 :
2024-08-16 01:11:06 +02:00
return render_template (
" sco_page.j2 " ,
title = " Coefficients des UE du semestre " ,
content = " <h2>Coefficients des UE du semestre</h2> " + " \n " . join ( H ) + tf [ 1 ] ,
)
2020-09-26 16:19:37 +02:00
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 = [ ]
2024-02-14 21:45:58 +01:00
ue_modified : list [ tuple [ UniteEns , float ] ] = [ ]
2020-09-26 16:19:37 +02:00
msg = [ ]
for ue in ues :
2024-02-14 21:45:58 +01:00
val = tf [ 2 ] [ " ue_ " + str ( ue . id ) ]
2021-01-17 22:31:28 +01:00
coefs = sco_formsemestre . formsemestre_uecoef_list (
2024-02-14 21:45:58 +01:00
cnx , args = { " formsemestre_id " : formsemestre_id , " ue_id " : ue . id }
2020-09-26 16:19:37 +02:00
)
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 ) :
2024-02-14 21:45:58 +01:00
ue_modified . append ( ( ue , val ) )
except ValueError :
2020-09-26 16:19:37 +02:00
ok = False
msg . append (
2024-02-14 21:45:58 +01:00
f " valeur invalide ( { val } ) pour le coefficient de l ' UE { ue . acronyme } "
2020-09-26 16:19:37 +02:00
)
if not ok :
2024-08-16 01:11:06 +02:00
render_template (
" sco_page.j2 " ,
title = " Coefficients des UE du semestre " ,
content = " <h2>Coefficients des UE du semestre</h2> "
+ " \n " . join ( H )
2020-09-26 16:19:37 +02:00
+ " <p><ul><li> %s </li></ul></p> " % " </li><li> " . join ( msg )
2024-08-16 01:11:06 +02:00
+ tf [ 1 ] ,
2020-09-26 16:19:37 +02:00
)
# apply modifications
2024-02-14 21:45:58 +01:00
for ue , val in ue_modified :
2021-01-17 22:31:28 +01:00
sco_formsemestre . do_formsemestre_uecoef_edit_or_create (
2024-02-14 21:45:58 +01:00
cnx , formsemestre_id , ue . id , val
2020-09-26 16:19:37 +02:00
)
for ue in ue_deleted :
2024-02-14 21:45:58 +01:00
sco_formsemestre . do_formsemestre_uecoef_delete ( cnx , formsemestre_id , ue . id )
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> """ )
2024-02-14 21:45:58 +01:00
for ue , val in ue_modified :
message . append ( f " <li> { ue . acronyme } : { val } </li> " )
2022-10-01 15:34:39 +02:00
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 :
2024-02-14 21:45:58 +01:00
message . append ( f " <li> { ue . acronyme } </li> " )
2022-10-01 15:34:39 +02:00
message . append ( " </ul> " )
2024-08-16 01:11:06 +02:00
sco_cache . invalidate_formsemestre (
formsemestre_id = formsemestre_id
) # > modif coef UE cap (modifs notes de _certains_ etudiants)
2020-09-26 16:19:37 +02:00
else :
2022-10-01 15:34:39 +02:00
message = [ """ <h3>Aucune modification</h3> """ ]
2020-09-26 16:19:37 +02:00
2024-08-16 01:11:06 +02:00
return render_template (
" sco_page.j2 " ,
title = " Coefficients des UE du semestre " ,
content = f """
< h2 > Coefficients des UE du semestre < / h2 >
{ " " . join ( message ) }
< p > < a class = " stdlink " href = " { url_for(
" notes.formsemestre_status " ,
2022-10-01 15:34:39 +02:00
scodoc_dept = g . scodoc_dept , formsemestre_id = formsemestre_id )
} " >Revenir au tableau de bord</a>
< / p >
2024-08-16 01:11:06 +02:00
""" ,
)
2020-09-26 16:19:37 +02:00
2024-02-14 21:45:58 +01:00
def _get_sem_ues_modimpls (
formsemestre : FormSemestre ,
) - > tuple [ list [ UniteEns ] , list [ ModuleImpl ] ] :
2023-02-20 21:04:29 +01:00
""" Get liste des UE du semestre (à partir des moduleimpls)
( utilisé quand on ne peut pas construire nt et faire nt . get_ues_stat_dict ( ) )
"""
uedict = { }
2024-02-14 21:45:58 +01:00
modimpls = formsemestre . modimpls . all ( )
2023-02-20 21:04:29 +01:00
for modimpl in modimpls :
2024-02-14 21:45:58 +01:00
if not modimpl . module . ue_id in uedict :
uedict [ modimpl . module . ue . id ] = modimpl . module . ue
2023-02-20 21:04:29 +01:00
ues = list ( uedict . values ( ) )
2024-02-14 21:45:58 +01:00
ues . sort ( key = lambda u : u . numero )
2023-02-20 21:04:29 +01:00
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
)