2021-05-31 00:14:15 +02:00
# -*- coding: utf-8 -*-
2021-06-02 22:40:34 +02:00
##############################################################################
#
# Gestion scolarite IUT
#
2022-01-01 14:49:42 +01:00
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
2021-06-02 22:40:34 +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
#
##############################################################################
2021-05-31 00:14:15 +02:00
"""
Module absences : issu de ScoDoc7 / ZAbsences . py
Emmanuel Viennet , 2021
2021-06-02 22:40:34 +02:00
Gestion des absences ( v4 )
Code dérivé de la partie la plus ancienne de ScoDoc , et à revoir .
L ' API de plus bas niveau est en gros:
2021-08-21 00:24:51 +02:00
AnnuleAbsencesDatesNoJust ( dates )
2021-07-19 19:53:01 +02:00
count_abs ( etudid , debut , fin , matin = None , moduleimpl_id = None )
count_abs_just ( etudid , debut , fin , matin = None , moduleimpl_id = None )
list_abs_just ( etudid , datedebut ) [ pas de fin ? ]
list_abs_non_just ( etudid , datedebut ) [ pas de fin ? ]
list_abs_justifs ( etudid , datedebut , datefin = None , only_no_abs = True )
2021-06-02 22:40:34 +02:00
2021-07-19 19:53:01 +02:00
list_abs_jour ( date , am = True , pm = True , is_abs = None , is_just = None )
list_abs_non_just_jour ( date , am = True , pm = True )
2021-06-02 22:40:34 +02:00
2021-05-31 00:14:15 +02:00
"""
2021-07-11 13:03:13 +02:00
import calendar
2021-06-02 22:40:34 +02:00
import datetime
import dateutil
import dateutil . parser
2021-07-11 13:03:13 +02:00
import re
import time
2021-09-16 14:58:56 +02:00
import urllib
2021-07-11 13:03:13 +02:00
from xml . etree import ElementTree
2021-06-02 22:40:34 +02:00
2021-08-01 10:16:16 +02:00
import flask
2021-09-18 10:10:02 +02:00
from flask import g , request
2021-07-11 17:37:12 +02:00
from flask import url_for
2021-09-18 13:42:19 +02:00
from flask_login import current_user
2021-05-31 00:14:15 +02:00
2022-08-01 21:42:19 +02:00
from app import db , log
from app import api
2022-02-13 23:53:11 +01:00
from app . comp import res_sem
2022-03-27 22:25:00 +02:00
from app . comp . res_compat import NotesTableCompat
2021-05-31 00:14:15 +02:00
from app . decorators import (
2021-08-13 00:34:58 +02:00
scodoc ,
2021-05-31 00:14:15 +02:00
scodoc7func ,
permission_required ,
2021-09-09 16:11:05 +02:00
permission_required_compat_scodoc7 ,
2021-05-31 00:14:15 +02:00
)
2022-04-08 16:36:56 +02:00
from app . models import FormSemestre , GroupDescr
2022-02-13 23:53:11 +01:00
from app . models . absences import BilletAbsence
2021-05-31 00:14:15 +02:00
from app . views import absences_bp as bp
2021-06-02 22:40:34 +02:00
# ---------------
from app . scodoc import sco_utils as scu
2021-06-15 13:59:56 +02:00
from app . scodoc import notesdb as ndb
2021-06-02 22:40:34 +02:00
from app . scodoc . scolog import logdb
2021-06-19 23:21:37 +02:00
from app . scodoc . sco_permissions import Permission
2021-09-13 09:55:49 +02:00
from app . scodoc . sco_exceptions import ScoValueError , APIInvalidParams
2021-06-19 23:21:37 +02:00
from app . scodoc . TrivialFormulator import TrivialFormulator
2021-06-02 22:40:34 +02:00
from app . scodoc . gen_tables import GenTable
from app . scodoc import html_sco_header
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_abs
2022-08-01 21:42:19 +02:00
from app . scodoc import sco_abs_billets
2021-06-21 10:17:16 +02:00
from app . scodoc import sco_abs_views
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_etud
2021-07-09 10:26:31 +02:00
from app . scodoc import sco_find_etud
2021-06-02 22:40:34 +02:00
from app . scodoc import sco_formsemestre
from app . scodoc import sco_groups_view
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_moduleimpl
from app . scodoc import sco_preferences
2021-07-11 13:03:13 +02:00
from app . scodoc import sco_xml
2021-06-19 23:21:37 +02:00
2021-06-02 22:40:34 +02:00
CSSSTYLES = html_sco_header . BOOTSTRAP_MULTISELECT_CSS
2021-07-09 10:26:31 +02:00
def sco_publish ( route , function , permission , methods = [ " GET " ] ) :
2021-06-12 22:43:22 +02:00
""" Declare a route for a python function,
protected by permission and called following ScoDoc 7 Zope standards .
"""
2021-07-09 10:26:31 +02:00
return bp . route ( route , methods = methods ) (
2021-08-21 00:24:51 +02:00
scodoc ( permission_required ( permission ) ( scodoc7func ( function ) ) )
2021-07-09 10:26:31 +02:00
)
2021-06-12 22:43:22 +02:00
2021-06-02 22:40:34 +02:00
# --------------------------------------------------------------------
#
# ABSENCES (/ScoDoc/<dept>/Scolarite/Absences/...)
#
# --------------------------------------------------------------------
2021-07-09 10:26:31 +02:00
@bp.route ( " / " )
@bp.route ( " /index_html " )
2021-08-13 00:34:58 +02:00
@scodoc
2021-07-09 10:26:31 +02:00
@permission_required ( Permission . ScoView )
2021-08-21 00:24:51 +02:00
@scodoc7func
2021-09-24 12:10:53 +02:00
def index_html ( ) :
2021-07-09 10:26:31 +02:00
""" Gestionnaire absences, page principale """
H = [
html_sco_header . sco_header (
2022-04-08 16:36:56 +02:00
page_title = " Saisie des absences " ,
2021-07-09 10:26:31 +02:00
cssstyles = [ " css/calabs.css " ] ,
javascripts = [ " js/calabs.js " ] ,
) ,
2022-04-08 16:36:56 +02:00
""" <h2>Traitement des absences</h2>
< p class = " help " >
Pour saisir des absences ou consulter les états , il est recommandé par passer par
le semestre concerné ( saisie par jours nommés ou par semaines ) .
< / p >
""" ,
2021-07-09 10:26:31 +02:00
]
2022-04-08 16:36:56 +02:00
H . append (
""" <p class= " help " >Pour signaler, annuler ou justifier une absence pour un seul étudiant,
choisissez d ' abord concerné:</p> " " "
)
H . append ( sco_find_etud . form_search_etud ( ) )
if current_user . has_permission (
Permission . ScoAbsChange
) and sco_preferences . get_preference ( " handle_billets_abs " ) :
2021-07-09 10:26:31 +02:00
H . append (
2022-08-01 21:42:19 +02:00
f """
2022-04-08 16:36:56 +02:00
< h2 style = " margin-top: 30px; " > Billets d ' absence</h2>
2022-08-01 21:42:19 +02:00
< ul > < li > < a href = " { url_for( " absences . list_billets " , scodoc_dept=g.scodoc_dept)
} " >Traitement des billets d ' absence en attente</a>
< / li > < / ul >
2022-04-08 16:36:56 +02:00
"""
)
2021-07-29 10:19:00 +02:00
H . append ( html_sco_header . sco_footer ( ) )
2021-07-09 10:26:31 +02:00
return " \n " . join ( H )
2022-04-08 16:36:56 +02:00
@bp.route ( " /choix_semaine " )
@scodoc
@permission_required ( Permission . ScoAbsChange )
@scodoc7func
def choix_semaine ( group_id ) :
""" Page choix semaine sur calendrier pour saisie absences d ' un groupe """
group = GroupDescr . query . get_or_404 ( group_id )
H = [
html_sco_header . sco_header (
page_title = " Saisie des absences " ,
cssstyles = [ " css/calabs.css " ] ,
javascripts = [ " js/calabs.js " ] ,
) ,
f """
< h2 > Saisie des Absences < / h2 >
< form action = " SignaleAbsenceGrHebdo " id = " formw " >
< p >
< span style = " font-weight: bold; font-size:120 % ; " >
Saisie par semaine < / span > - Groupe : { group . get_nom_with_part ( ) }
< input name = " datelundi " type = " hidden " value = " x " / >
< input name = " group_ids " type = " hidden " value = " {group_id} " / >
< / p >
""" ,
cal_select_week ( ) ,
""" <p class= " help " >Sélectionner le groupe d ' étudiants, puis cliquez sur une semaine pour
saisir les absences de toute cette semaine . < / p >
< / form >
""" ,
html_sco_header . sco_footer ( ) ,
]
return " \n " . join ( H )
2021-08-21 00:24:51 +02:00
def cal_select_week ( year = None ) :
2021-07-09 10:26:31 +02:00
" display calendar allowing week selection "
if not year :
2021-08-01 16:13:47 +02:00
year = scu . AnneeScolaire ( )
2021-08-19 10:28:35 +02:00
sems = sco_formsemestre . do_formsemestre_list ( )
2021-07-09 10:26:31 +02:00
if not sems :
js = " "
else :
js = ' onmouseover= " highlightweek(this); " onmouseout= " deselectweeks(); " onclick= " wclick(this); " '
2021-08-21 00:24:51 +02:00
C = sco_abs . YearTable ( int ( year ) , dayattributes = js )
2021-07-09 10:26:31 +02:00
return C
2021-06-02 22:40:34 +02:00
sco_publish ( " /EtatAbsences " , sco_abs_views . EtatAbsences , Permission . ScoView )
sco_publish ( " /CalAbs " , sco_abs_views . CalAbs , Permission . ScoView )
sco_publish (
2021-07-09 10:26:31 +02:00
" /SignaleAbsenceEtud " ,
sco_abs_views . SignaleAbsenceEtud ,
Permission . ScoAbsChange ,
methods = [ " GET " , " POST " ] ,
)
sco_publish (
" /doSignaleAbsence " ,
sco_abs_views . doSignaleAbsence ,
Permission . ScoAbsChange ,
methods = [ " GET " , " POST " ] ,
2021-06-02 22:40:34 +02:00
)
sco_publish (
2021-07-09 10:26:31 +02:00
" /JustifAbsenceEtud " ,
sco_abs_views . JustifAbsenceEtud ,
Permission . ScoAbsChange ,
methods = [ " GET " , " POST " ] ,
2021-06-02 22:40:34 +02:00
)
sco_publish (
2021-07-09 10:26:31 +02:00
" /doJustifAbsence " ,
sco_abs_views . doJustifAbsence ,
Permission . ScoAbsChange ,
methods = [ " GET " , " POST " ] ,
2021-06-02 22:40:34 +02:00
)
sco_publish (
2021-07-09 10:26:31 +02:00
" /AnnuleAbsenceEtud " ,
sco_abs_views . AnnuleAbsenceEtud ,
Permission . ScoAbsChange ,
methods = [ " GET " , " POST " ] ,
)
sco_publish (
" /doAnnuleAbsence " ,
sco_abs_views . doAnnuleAbsence ,
Permission . ScoAbsChange ,
methods = [ " GET " , " POST " ] ,
)
sco_publish (
" /doAnnuleJustif " ,
sco_abs_views . doAnnuleJustif ,
Permission . ScoAbsChange ,
methods = [ " GET " , " POST " ] ,
2021-06-02 22:40:34 +02:00
)
2021-06-19 23:21:37 +02:00
sco_publish (
" /AnnuleAbsencesDatesNoJust " ,
sco_abs_views . AnnuleAbsencesDatesNoJust ,
Permission . ScoAbsChange ,
2021-07-09 10:26:31 +02:00
methods = [ " GET " , " POST " ] ,
2021-06-19 23:21:37 +02:00
)
2021-12-13 22:15:42 +01:00
# Antédiluvienne fonction: #deprecated
@bp.route ( " /ListeAbsEtud " , methods = [ " GET " , " POST " ] ) # pour compat anciens clients PHP
@scodoc
@permission_required_compat_scodoc7 ( Permission . ScoView )
@scodoc7func
def ListeAbsEtud (
2021-12-21 23:05:49 +01:00
etudid = None ,
code_nip = None ,
2021-12-13 22:15:42 +01:00
with_evals = True ,
format = " html " ,
absjust_only = 0 ,
sco_year = None ,
) :
return sco_abs_views . ListeAbsEtud (
2021-12-21 23:05:49 +01:00
etudid = etudid ,
code_nip = str ( code_nip ) ,
2021-12-13 22:15:42 +01:00
with_evals = with_evals ,
format = format ,
absjust_only = absjust_only ,
sco_year = sco_year ,
)
2021-06-02 22:40:34 +02:00
# --------------------------------------------------------------------
#
# SQL METHODS (xxx #sco8 not views => à déplacer)
#
# --------------------------------------------------------------------
2021-07-19 19:53:01 +02:00
# API backward compatibility
sco_publish ( " /CountAbs " , sco_abs . count_abs , Permission . ScoView )
sco_publish ( " /CountAbsJust " , sco_abs . count_abs_just , Permission . ScoView )
# TODO nouvel appel rendnat les deux valeurs et utilisant le cache
2021-06-02 22:40:34 +02:00
2021-07-09 10:26:31 +02:00
@bp.route ( " /doSignaleAbsenceGrSemestre " , methods = [ " GET " , " POST " ] )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoAbsChange )
2021-08-21 00:24:51 +02:00
@scodoc7func
2021-06-02 22:40:34 +02:00
def doSignaleAbsenceGrSemestre (
moduleimpl_id = None ,
abslist = [ ] ,
dates = " " ,
etudids = " " ,
destination = None ,
) :
""" Enregistre absences aux dates indiquees (abslist et dates).
dates est une liste de dates ISO ( séparées par des ' , ' ) .
Efface les absences aux dates indiquées par dates ,
ou bien ajoute celles de abslist .
"""
2021-09-12 23:06:23 +02:00
moduleimpl_id = moduleimpl_id or None
2021-06-02 22:40:34 +02:00
if etudids :
2021-09-13 09:55:49 +02:00
etudids = [ int ( x ) for x in str ( etudids ) . split ( " , " ) ]
2021-06-02 22:40:34 +02:00
else :
etudids = [ ]
if dates :
dates = dates . split ( " , " )
else :
dates = [ ]
# 1- Efface les absences
if dates :
for etudid in etudids :
2021-08-21 00:24:51 +02:00
sco_abs_views . AnnuleAbsencesDatesNoJust ( etudid , dates , moduleimpl_id )
2021-06-02 22:40:34 +02:00
return " Absences effacées "
# 2- Ajoute les absences
if abslist :
2021-09-24 12:10:53 +02:00
sco_abs . add_abslist ( abslist , moduleimpl_id )
2021-06-02 22:40:34 +02:00
return " Absences ajoutées "
2021-09-24 12:10:53 +02:00
return ( " " , 204 )
2021-06-02 22:40:34 +02:00
# ------------ HTML Interfaces
2021-07-09 10:26:31 +02:00
@bp.route ( " /SignaleAbsenceGrHebdo " , methods = [ " GET " , " POST " ] )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoAbsChange )
2021-08-21 00:24:51 +02:00
@scodoc7func
2021-06-02 22:40:34 +02:00
def SignaleAbsenceGrHebdo (
2021-09-16 14:58:56 +02:00
datelundi , group_ids = [ ] , destination = " " , moduleimpl_id = None , formsemestre_id = None
2021-06-02 22:40:34 +02:00
) :
" Saisie hebdomadaire des absences "
if not moduleimpl_id :
moduleimpl_id = None
groups_infos = sco_groups_view . DisplayedGroupsInfos (
2021-09-16 14:58:56 +02:00
group_ids , moduleimpl_id = moduleimpl_id , formsemestre_id = formsemestre_id
2021-06-02 22:40:34 +02:00
)
if not groups_infos . members :
return (
2021-07-29 16:58:18 +02:00
html_sco_header . sco_header ( page_title = " Saisie des absences " )
2021-06-02 22:40:34 +02:00
+ " <h3>Aucun étudiant !</h3> "
2021-07-29 10:19:00 +02:00
+ html_sco_header . sco_footer ( )
2021-06-02 22:40:34 +02:00
)
2021-05-31 00:14:15 +02:00
2021-06-02 22:40:34 +02:00
base_url = " SignaleAbsenceGrHebdo?datelundi= %s & %s &destination= %s " % (
datelundi ,
groups_infos . groups_query_args ,
2021-09-16 14:58:56 +02:00
urllib . parse . quote ( destination ) ,
2021-06-02 22:40:34 +02:00
)
2021-05-31 00:14:15 +02:00
2021-06-02 22:40:34 +02:00
formsemestre_id = groups_infos . formsemestre_id
2021-06-14 00:23:22 +02:00
require_module = sco_preferences . get_preference (
2021-07-28 17:03:54 +02:00
" abs_require_module " , formsemestre_id
2021-06-14 00:23:22 +02:00
)
2021-06-02 22:40:34 +02:00
etuds = [
2021-06-19 23:21:37 +02:00
sco_etud . get_etud_info ( etudid = m [ " etudid " ] , filled = True ) [ 0 ]
2021-06-02 22:40:34 +02:00
for m in groups_infos . members
]
# Restreint aux inscrits au module sélectionné
if moduleimpl_id :
mod_inscrits = set (
[
x [ " etudid " ]
for x in sco_moduleimpl . do_moduleimpl_inscription_list (
2021-08-20 01:09:55 +02:00
moduleimpl_id = moduleimpl_id
2021-06-02 22:40:34 +02:00
)
]
)
etuds_inscrits_module = [ e for e in etuds if e [ " etudid " ] in mod_inscrits ]
if etuds_inscrits_module :
etuds = etuds_inscrits_module
else :
# Si aucun etudiant n'est inscrit au module choisi...
moduleimpl_id = None
2022-02-13 23:53:11 +01:00
formsemestre = FormSemestre . query . get_or_404 ( formsemestre_id )
nt : NotesTableCompat = res_sem . load_formsemestre_results ( formsemestre )
sem = formsemestre . to_dict ( )
# sem = sco_formsemestre.do_formsemestre_list({"formsemestre_id": formsemestre_id})[0]
2021-06-02 22:40:34 +02:00
# calcule dates jours de cette semaine
# liste de dates iso "yyyy-mm-dd"
2021-06-15 13:59:56 +02:00
datessem = [ ndb . DateDMYtoISO ( datelundi ) ]
2021-08-21 00:24:51 +02:00
for _ in sco_abs . day_names ( ) [ 1 : ] :
datessem . append ( sco_abs . next_iso_day ( datessem [ - 1 ] ) )
2021-06-02 22:40:34 +02:00
#
if groups_infos . tous_les_etuds_du_sem :
gr_tit = " en "
else :
if len ( groups_infos . group_ids ) > 1 :
p = " des groupes "
else :
p = " du groupe "
gr_tit = p + ' <span class= " fontred " > ' + groups_infos . groups_titles + " </span> "
H = [
2021-06-13 18:29:53 +02:00
html_sco_header . sco_header (
2021-06-02 22:40:34 +02:00
page_title = " Saisie hebdomadaire des absences " ,
init_qtip = True ,
javascripts = html_sco_header . BOOTSTRAP_MULTISELECT_JS
+ [
" js/etud_info.js " ,
" js/abs_ajax.js " ,
" js/groups_view.js " ,
] ,
cssstyles = CSSSTYLES ,
no_side_bar = 1 ,
) ,
""" <table border= " 0 " cellspacing= " 16 " ><tr><td>
< h2 > Saisie des absences % s % s ,
< span class = " fontred " > semaine du lundi % s < / span > < / h2 >
< div >
< form id = " group_selector " method = " get " >
< input type = " hidden " name = " formsemestre_id " id = " formsemestre_id " value = " %s " / >
< input type = " hidden " name = " datelundi " id = " datelundi " value = " %s " / >
< input type = " hidden " name = " destination " id = " destination " value = " %s " / >
< input type = " hidden " name = " moduleimpl_id " id = " moduleimpl_id_o " value = " %s " / >
Groupes : % s
< / form >
< form id = " abs_form " >
"""
% (
gr_tit ,
sem [ " titre_num " ] ,
datelundi ,
groups_infos . formsemestre_id ,
datelundi ,
destination ,
moduleimpl_id or " " ,
2021-08-20 10:51:42 +02:00
sco_groups_view . menu_groups_choice ( groups_infos , submit_on_change = True ) ,
2021-06-02 22:40:34 +02:00
) ,
]
#
modimpls_list = [ ]
2021-12-24 00:08:25 +01:00
ues = nt . get_ues_stat_dict ( )
2021-06-02 22:40:34 +02:00
for ue in ues :
2021-12-26 19:15:47 +01:00
modimpls_list + = nt . get_modimpls_dict ( ue_id = ue [ " ue_id " ] )
2021-06-02 22:40:34 +02:00
menu_module = " "
for modimpl in modimpls_list :
if modimpl [ " moduleimpl_id " ] == moduleimpl_id :
sel = " selected "
else :
sel = " "
menu_module + = (
""" <option value= " %(modimpl_id)s " %(sel)s > %(modname)s </option> \n """
% {
" modimpl_id " : modimpl [ " moduleimpl_id " ] ,
2022-03-29 22:43:40 +02:00
" modname " : ( modimpl [ " module " ] [ " code " ] or " " )
2021-06-02 22:40:34 +02:00
+ " "
2022-02-14 10:05:55 +01:00
+ ( modimpl [ " module " ] [ " abbrev " ] or modimpl [ " module " ] [ " titre " ] or " " ) ,
2021-06-02 22:40:34 +02:00
" sel " : sel ,
}
)
if moduleimpl_id :
sel = " "
else :
sel = " selected " # aucun module specifie
H . append (
""" Module concerné:
< select id = " moduleimpl_id " name = " moduleimpl_id " onchange = " change_moduleimpl( ' %(url)s ' ) " >
< option value = " " % ( sel ) s > non spécifié < / option >
% ( menu_module ) s
< / select >
< / div > """
% { " menu_module " : menu_module , " url " : base_url , " sel " : sel }
)
2021-06-19 23:21:37 +02:00
H + = _gen_form_saisie_groupe (
2021-08-21 00:24:51 +02:00
etuds , datessem , destination , moduleimpl_id , require_module
2021-06-02 22:40:34 +02:00
)
2021-07-29 10:19:00 +02:00
H . append ( html_sco_header . sco_footer ( ) )
2021-06-02 22:40:34 +02:00
return " \n " . join ( H )
2021-07-09 10:26:31 +02:00
@bp.route ( " /SignaleAbsenceGrSemestre " , methods = [ " GET " , " POST " ] )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoAbsChange )
2021-08-21 00:24:51 +02:00
@scodoc7func
2021-06-02 22:40:34 +02:00
def SignaleAbsenceGrSemestre (
datedebut ,
datefin ,
destination = " " ,
2022-04-08 16:36:56 +02:00
group_ids = ( ) , # list of groups to display
2021-06-02 22:40:34 +02:00
nbweeks = 4 , # ne montre que les nbweeks dernieres semaines
moduleimpl_id = None ,
) :
""" Saisie des absences sur une journée sur un semestre (ou intervalle de dates) entier """
2021-09-08 00:34:45 +02:00
groups_infos = sco_groups_view . DisplayedGroupsInfos ( group_ids )
2021-06-02 22:40:34 +02:00
if not groups_infos . members :
return (
2021-07-29 16:58:18 +02:00
html_sco_header . sco_header ( page_title = " Saisie des absences " )
2021-06-02 22:40:34 +02:00
+ " <h3>Aucun étudiant !</h3> "
2021-07-29 10:19:00 +02:00
+ html_sco_header . sco_footer ( )
2021-06-02 22:40:34 +02:00
)
formsemestre_id = groups_infos . formsemestre_id
2022-02-13 23:53:11 +01:00
formsemestre : FormSemestre = FormSemestre . query . get_or_404 ( formsemestre_id )
sem = formsemestre . to_dict ( )
2021-06-14 00:23:22 +02:00
require_module = sco_preferences . get_preference (
2021-07-28 17:03:54 +02:00
" abs_require_module " , formsemestre_id
2021-06-14 00:23:22 +02:00
)
2021-06-02 22:40:34 +02:00
etuds = [
2021-06-19 23:21:37 +02:00
sco_etud . get_etud_info ( etudid = m [ " etudid " ] , filled = True ) [ 0 ]
2021-06-02 22:40:34 +02:00
for m in groups_infos . members
]
# Restreint aux inscrits au module sélectionné
if moduleimpl_id :
mod_inscrits = set (
[
x [ " etudid " ]
for x in sco_moduleimpl . do_moduleimpl_inscription_list (
2021-08-20 01:09:55 +02:00
moduleimpl_id = moduleimpl_id
2021-06-02 22:40:34 +02:00
)
]
)
etuds = [ e for e in etuds if e [ " etudid " ] in mod_inscrits ]
if not moduleimpl_id :
moduleimpl_id = None
base_url_noweeks = (
" SignaleAbsenceGrSemestre?datedebut= %s &datefin= %s & %s &destination= %s "
% (
datedebut ,
datefin ,
groups_infos . groups_query_args ,
2021-09-16 14:58:56 +02:00
urllib . parse . quote ( destination ) ,
2021-06-02 22:40:34 +02:00
)
)
base_url = base_url_noweeks + " &nbweeks= %s " % nbweeks # sans le moduleimpl_id
if etuds :
2022-02-13 23:53:11 +01:00
nt : NotesTableCompat = res_sem . load_formsemestre_results ( formsemestre )
2022-02-04 11:19:01 +01:00
2021-08-21 00:24:51 +02:00
work_saturday = sco_abs . is_work_saturday ( )
2021-06-19 23:21:37 +02:00
jourdebut = sco_abs . ddmmyyyy ( datedebut , work_saturday = work_saturday )
jourfin = sco_abs . ddmmyyyy ( datefin , work_saturday = work_saturday )
today = sco_abs . ddmmyyyy (
2021-06-02 22:40:34 +02:00
time . strftime ( " %d / % m/ % Y " , time . localtime ( ) ) ,
work_saturday = work_saturday ,
)
2021-07-09 10:26:31 +02:00
today . next_day ( )
2021-06-02 22:40:34 +02:00
if jourfin > today : # ne propose jamais les semaines dans le futur
jourfin = today
if jourdebut > today :
raise ScoValueError ( " date de début dans le futur ( %s ) ! " % jourdebut )
#
if not jourdebut . iswork ( ) or jourdebut > jourfin :
raise ValueError (
" date debut invalide ( %s , ouvrable= %d ) "
% ( str ( jourdebut ) , jourdebut . iswork ( ) )
)
# calcule dates
2021-06-19 23:21:37 +02:00
dates = [ ] # sco_abs.ddmmyyyy instances
d = sco_abs . ddmmyyyy ( datedebut , work_saturday = work_saturday )
2021-06-02 22:40:34 +02:00
while d < = jourfin :
dates . append ( d )
2021-07-09 10:26:31 +02:00
d = d . next_day ( 7 ) # avance d'une semaine
2021-06-02 22:40:34 +02:00
#
msg = " Montrer seulement les 4 dernières semaines "
nwl = 4
if nbweeks :
nbweeks = int ( nbweeks )
if nbweeks > 0 :
dates = dates [ - nbweeks : ]
msg = " Montrer toutes les semaines "
nwl = 0
url_link_semaines = base_url_noweeks + " &nbweeks= %s " % nwl
if moduleimpl_id :
2021-08-21 23:45:48 +02:00
url_link_semaines + = " &moduleimpl_id= " + str ( moduleimpl_id )
2021-06-02 22:40:34 +02:00
#
dates = [ x . ISO ( ) for x in dates ]
2022-04-08 16:36:56 +02:00
day_name = sco_abs . day_names ( ) [ jourdebut . weekday ]
2021-06-02 22:40:34 +02:00
if groups_infos . tous_les_etuds_du_sem :
gr_tit = " en "
else :
if len ( groups_infos . group_ids ) > 1 :
p = " des groupes "
else :
p = " du groupe "
gr_tit = p + ' <span class= " fontred " > ' + groups_infos . groups_titles + " </span> "
H = [
2021-06-13 18:29:53 +02:00
html_sco_header . sco_header (
2022-04-08 16:36:56 +02:00
page_title = f " Saisie des absences du { day_name } " ,
2021-06-02 22:40:34 +02:00
init_qtip = True ,
javascripts = [ " js/etud_info.js " , " js/abs_ajax.js " ] ,
no_side_bar = 1 ,
) ,
2022-04-08 16:36:56 +02:00
f """ <table border= " 0 " cellspacing= " 16 " ><tr><td>
< h2 > Saisie des absences { gr_tit } { sem [ " titre_num " ] } ,
les < span class = " fontred " > { day_name } s < / span > < / h2 >
2021-06-02 22:40:34 +02:00
< p >
2022-04-08 16:36:56 +02:00
< a href = " {url_link_semaines} " > { msg } < / a >
2021-06-02 22:40:34 +02:00
< form id = " abs_form " action = " doSignaleAbsenceGrSemestre " method = " post " >
2022-04-08 16:36:56 +02:00
""" ,
2021-06-02 22:40:34 +02:00
]
#
if etuds :
modimpls_list = [ ]
2021-12-24 00:08:25 +01:00
ues = nt . get_ues_stat_dict ( )
2021-06-02 22:40:34 +02:00
for ue in ues :
2021-12-26 19:15:47 +01:00
modimpls_list + = nt . get_modimpls_dict ( ue_id = ue [ " ue_id " ] )
2021-06-02 22:40:34 +02:00
menu_module = " "
for modimpl in modimpls_list :
if modimpl [ " moduleimpl_id " ] == moduleimpl_id :
sel = " selected "
else :
sel = " "
menu_module + = (
""" <option value= " %(modimpl_id)s " %(sel)s > %(modname)s </option> \n """
% {
" modimpl_id " : modimpl [ " moduleimpl_id " ] ,
2022-03-01 19:27:03 +01:00
" modname " : ( modimpl [ " module " ] [ " code " ] or " " )
2021-06-02 22:40:34 +02:00
+ " "
2022-03-18 19:33:07 +01:00
+ ( modimpl [ " module " ] [ " abbrev " ] or modimpl [ " module " ] [ " titre " ] or " " ) ,
2021-06-02 22:40:34 +02:00
" sel " : sel ,
}
)
if moduleimpl_id :
sel = " "
else :
sel = " selected " # aucun module specifie
H . append (
""" <p>
2022-03-01 19:27:03 +01:00
Module concerné par ces absences ( % ( optionel_txt ) s ) :
2021-06-02 22:40:34 +02:00
< select id = " moduleimpl_id " name = " moduleimpl_id "
onchange = " document.location= ' %(url)s &moduleimpl_id= ' +document.getElementById( ' moduleimpl_id ' ).value " >
< option value = " " % ( sel ) s > non spécifié < / option >
% ( menu_module ) s
< / select >
< / p > """
% {
" menu_module " : menu_module ,
" url " : base_url ,
" sel " : sel ,
" optionel_txt " : ' <span class= " redboldtext " >requis</span> '
if require_module
else " optionnel " ,
}
)
2021-06-19 23:21:37 +02:00
H + = _gen_form_saisie_groupe (
2021-08-21 00:24:51 +02:00
etuds , dates , destination , moduleimpl_id , require_module
2021-06-02 22:40:34 +02:00
)
2021-07-29 10:19:00 +02:00
H . append ( html_sco_header . sco_footer ( ) )
2021-06-02 22:40:34 +02:00
return " \n " . join ( H )
def _gen_form_saisie_groupe (
2021-08-21 00:24:51 +02:00
etuds , dates , destination = " " , moduleimpl_id = None , require_module = False
2021-06-02 22:40:34 +02:00
) :
""" Formulaire saisie absences
Args :
etuds : liste des étudiants
dates : liste ordonnée de dates iso , par exemple : [ ' 2020-12-24 ' , . . . ]
moduleimpl_id : optionnel , module concerné .
"""
H = [
"""
< script type = " text/javascript " >
$ ( function ( ) {
$ ( " .abs_form_table input " ) . prop ( " disabled " , % s ) ;
} ) ;
function colorize ( obj ) {
if ( obj . checked ) {
obj . parentNode . className = ' absent ' ;
} else {
obj . parentNode . className = ' present ' ;
}
}
function on_toggled ( obj , etudid , dat ) {
colorize ( obj ) ;
if ( obj . checked ) {
ajaxFunction ( ' add ' , etudid , dat ) ;
} else {
ajaxFunction ( ' remove ' , etudid , dat ) ;
}
2021-05-31 00:14:15 +02:00
}
2021-06-02 22:40:34 +02:00
< / script >
< div id = " AjaxDiv " > < / div >
< br / >
< table rules = " cols " frame = " box " class = " abs_form_table " >
< tr > < th class = " formabs_contetud " > % d étudiants < / th >
"""
% (
" true " if ( require_module and not moduleimpl_id ) else " false " ,
len ( etuds ) ,
)
]
# Dates
odates = [ datetime . date ( * [ int ( x ) for x in d . split ( " - " ) ] ) for d in dates ]
begin = dates [ 0 ]
end = dates [ - 1 ]
# Titres colonnes
noms_jours = [ ] # eg [ "Lundi", "mardi", "Samedi", ... ]
2021-08-21 00:24:51 +02:00
jn = sco_abs . day_names ( )
2021-06-02 22:40:34 +02:00
for d in odates :
idx_jour = d . weekday ( )
noms_jours . append ( jn [ idx_jour ] )
for jour in noms_jours :
H . append (
' <th colspan= " 2 " width= " 100px " style= " padding-left: 5px; padding-right: 5px; " > '
+ jour
+ " </th> "
)
H . append ( " </tr><tr><td> </td> " )
for d in odates :
H . append (
' <th colspan= " 2 " width= " 100px " style= " padding-left: 5px; padding-right: 5px; " > '
+ d . strftime ( " %d / % m/ % Y " )
+ " </th> "
)
H . append ( " </tr><tr><td> </td> " )
H . append ( " <th>AM</th><th>PM</th> " * len ( dates ) )
H . append ( " </tr> " )
#
if not etuds :
H . append (
' <tr><td><span class= " redboldtext " >Aucun étudiant inscrit !</span></td></tr> '
)
i = 1
2021-06-15 13:59:56 +02:00
cnx = ndb . GetDBConnexion ( )
cursor = cnx . cursor ( cursor_factory = ndb . ScoDocCursor )
2021-06-02 22:40:34 +02:00
for etud in etuds :
i + = 1
etudid = etud [ " etudid " ]
2021-11-07 10:00:50 +01:00
etud_class = " etudinfo " # css
2021-06-02 22:40:34 +02:00
# UE capitalisee dans semestre courant ?
cap = [ ]
if etud [ " cursem " ] :
2022-02-13 23:53:11 +01:00
formsemestre = FormSemestre . query . get_or_404 (
etud [ " cursem " ] [ " formsemestre_id " ]
)
nt : NotesTableCompat = res_sem . load_formsemestre_results ( formsemestre )
2021-12-24 00:08:25 +01:00
for ue in nt . get_ues_stat_dict ( ) :
2022-02-12 22:57:46 +01:00
ue_status = nt . get_etud_ue_status ( etudid , ue [ " ue_id " ] )
if ue_status and ue_status [ " is_capitalized " ] :
2021-06-02 22:40:34 +02:00
cap . append ( ue [ " acronyme " ] )
if cap :
capstr = ' <span class= " capstr " >( %s cap.)</span> ' % " , " . join ( cap )
else :
capstr = " "
2021-11-06 18:41:57 +01:00
if etud [ " etatincursem " ] == " D " :
2021-11-07 10:00:50 +01:00
capstr + = ' <span class= " capstr " >(dém.)</span> '
etud_class + = " etuddem "
2021-06-02 22:40:34 +02:00
tr_class = ( " row_1 " , " row_2 " , " row_3 " ) [ i % 3 ]
td_matin_class = ( " matin_1 " , " matin_2 " , " matin_3 " ) [ i % 3 ]
H . append (
2021-11-07 10:00:50 +01:00
' <tr class= " %s " ><td><b class= " %s " id= " %s " ><a class= " discretelink " href= " %s " target= " new " > %s </a></b> %s </td> '
2021-07-11 17:37:12 +02:00
% (
tr_class ,
2021-11-07 10:00:50 +01:00
etud_class ,
2021-07-11 17:37:12 +02:00
etudid ,
url_for ( " scolar.ficheEtud " , scodoc_dept = g . scodoc_dept , etudid = etudid ) ,
etud [ " nomprenom " ] ,
capstr ,
)
2021-06-02 22:40:34 +02:00
)
2021-06-19 23:21:37 +02:00
etud_abs = sco_abs . list_abs_in_range (
2021-07-19 19:53:01 +02:00
etudid , begin , end , moduleimpl_id = moduleimpl_id , cursor = cursor
2021-06-02 22:40:34 +02:00
)
for d in odates :
date = d . strftime ( " % Y- % m- %d " )
# matin
is_abs = { " jour " : d , " matin " : True } in etud_abs
if is_abs :
checked = " checked "
else :
checked = " "
# bulle lors du passage souris
coljour = sco_abs . DAYNAMES [ ( calendar . weekday ( d . year , d . month , d . day ) ) ]
datecol = coljour + " " + d . strftime ( " %d / % m/ % Y " )
bulle_am = ' " ' + etud [ " nomprenom " ] + " - " + datecol + ' (matin) " '
bulle_pm = ' " ' + etud [ " nomprenom " ] + " - " + datecol + ' (ap.midi) " '
H . append (
' <td class= " %s " ><a title= %s ><input type= " checkbox " name= " abslist:list " value= " %s " %s onclick= " on_toggled(this, \' %s \' , \' %s \' ) " /></a></td> '
% (
td_matin_class ,
bulle_am ,
2021-08-15 15:09:09 +02:00
str ( etudid ) + " : " + date + " : " + " am " ,
2021-06-02 22:40:34 +02:00
checked ,
etudid ,
date + " :am " ,
)
)
# après-midi
is_abs = { " jour " : d , " matin " : False } in etud_abs
if is_abs :
checked = " checked "
else :
checked = " "
H . append (
' <td><a title= %s ><input type= " checkbox " name= " abslist:list " value= " %s " %s onclick= " on_toggled(this, \' %s \' , \' %s \' ) " /></a></td> '
% (
bulle_pm ,
2021-08-16 08:33:12 +02:00
str ( etudid ) + " : " + date + " : " + " pm " ,
2021-06-02 22:40:34 +02:00
checked ,
etudid ,
date + " :pm " ,
)
)
H . append ( " </tr> " )
H . append ( " </table> " )
# place la liste des etudiants et les dates pour pouvoir effacer les absences
H . append (
' <input type= " hidden " name= " etudids " value= " %s " /> '
2021-08-16 08:33:12 +02:00
% " , " . join ( [ str ( etud [ " etudid " ] ) for etud in etuds ] )
2021-06-02 22:40:34 +02:00
)
H . append ( ' <input type= " hidden " name= " datedebut " value= " %s " /> ' % dates [ 0 ] )
H . append ( ' <input type= " hidden " name= " datefin " value= " %s " /> ' % dates [ - 1 ] )
H . append ( ' <input type= " hidden " name= " dates " value= " %s " /> ' % " , " . join ( dates ) )
H . append (
' <input type= " hidden " name= " destination " value= " %s " /> '
2021-09-16 14:58:56 +02:00
% urllib . parse . quote ( destination )
2021-06-02 22:40:34 +02:00
)
#
# version pour formulaire avec AJAX (Yann LB)
H . append (
"""
< / p >
< / form >
< / p >
< / td > < / tr > < / table >
< p class = " help " > Les cases cochées correspondent à des absences .
Les absences saisies ne sont pas justifiées ( sauf si un justificatif a été entré
par ailleurs ) .
< / p > < p class = " help " > Si vous " décochez " une case , l ' absence correspondante sera supprimée.
Attention , les modifications sont automatiquement entregistrées au fur et à mesure .
< / p >
2022-04-08 16:36:56 +02:00
"""
2021-06-02 22:40:34 +02:00
)
return H
@bp.route ( " /EtatAbsencesGr " )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoView )
2021-08-21 00:24:51 +02:00
@scodoc7func # ported from dtml
2021-06-02 22:40:34 +02:00
def EtatAbsencesGr (
group_ids = [ ] , # list of groups to display
debut = " " ,
fin = " " ,
with_boursier = True , # colonne boursier
format = " html " ,
) :
""" Liste les absences de groupes """
2021-06-15 13:59:56 +02:00
datedebut = ndb . DateDMYtoISO ( debut )
datefin = ndb . DateDMYtoISO ( fin )
2021-06-02 22:40:34 +02:00
# Informations sur les groupes à afficher:
2021-09-08 00:34:45 +02:00
groups_infos = sco_groups_view . DisplayedGroupsInfos ( group_ids )
2021-06-02 22:40:34 +02:00
formsemestre_id = groups_infos . formsemestre_id
sem = groups_infos . formsemestre
# Construit tableau (etudid, statut, nomprenom, nbJust, nbNonJust, NbTotal)
T = [ ]
for m in groups_infos . members :
2021-06-19 23:21:37 +02:00
etud = sco_etud . get_etud_info ( etudid = m [ " etudid " ] , filled = True ) [ 0 ]
2021-07-19 19:53:01 +02:00
nbabs = sco_abs . count_abs ( etudid = etud [ " etudid " ] , debut = datedebut , fin = datefin )
nbabsjust = sco_abs . count_abs_just (
etudid = etud [ " etudid " ] , debut = datedebut , fin = datefin
2021-06-02 22:40:34 +02:00
)
nbjustifs_noabs = len (
2021-07-19 19:53:01 +02:00
sco_abs . list_abs_justifs (
2022-05-03 02:37:14 +02:00
etudid = etud [ " etudid " ] ,
datedebut = datedebut ,
datefin = datefin ,
only_no_abs = True ,
2021-06-02 22:40:34 +02:00
)
)
# retrouve sem dans etud['sems']
s = None
for s in etud [ " sems " ] :
if s [ " formsemestre_id " ] == formsemestre_id :
break
if not s or s [ " formsemestre_id " ] != formsemestre_id :
raise ValueError (
" EtatAbsencesGr: can ' t retreive sem "
) # bug or malicious arg
T . append (
{
" etudid " : etud [ " etudid " ] ,
" etatincursem " : s [ " ins " ] [ " etat " ] ,
" nomprenom " : etud [ " nomprenom " ] ,
" nbabsjust " : nbabsjust ,
" nbabsnonjust " : nbabs - nbabsjust ,
" nbabs " : nbabs ,
" nbjustifs_noabs " : nbjustifs_noabs ,
" _nomprenom_target " : " CalAbs?etudid= %s " % etud [ " etudid " ] ,
" _nomprenom_td_attrs " : ' id= " %s " class= " etudinfo " ' % etud [ " etudid " ] ,
2022-05-03 02:37:14 +02:00
" boursier " : " oui " if etud [ " boursier " ] else " non " ,
2021-06-02 22:40:34 +02:00
}
)
if s [ " ins " ] [ " etat " ] == " D " :
T [ - 1 ] [ " _css_row_class " ] = " etuddem "
T [ - 1 ] [ " nomprenom " ] + = " (dem) "
columns_ids = [
" nomprenom " ,
" nbjustifs_noabs " ,
" nbabsjust " ,
" nbabsnonjust " ,
" nbabs " ,
]
if with_boursier :
columns_ids [ 1 : 1 ] = [ " boursier " ]
if groups_infos . tous_les_etuds_du_sem :
gr_tit = " "
else :
if len ( groups_infos . group_ids ) > 1 :
p = " des groupes "
else :
p = " du groupe "
if format == " html " :
h = ' <span class= " fontred " > ' + groups_infos . groups_titles + " </span> "
else :
h = groups_infos . groups_titles
gr_tit = p + h
2022-05-03 02:24:09 +02:00
title = f " État des absences { gr_tit } "
2021-06-02 22:40:34 +02:00
if format == " xls " or format == " xml " or format == " json " :
columns_ids = [ " etudid " ] + columns_ids
2022-05-03 02:24:09 +02:00
# --- Formulaire choix dates début / fin
form_date = (
f """
< form action = " {groups_infos.base_url} " method = " get " >
< input type = " hidden " name = " group_ids " value = " {group_ids} " >
< span style = " font-size: 120 % " > < b > Période du
< input type = " text " name = " debut " size = " 10 " value = " {debut} " class = " datepicker "
onchange = " validate_date(this); " >
& nbsp ; au & nbsp ;
< input type = " text " name = " fin " size = " 10 " value = " {fin} " class = " datepicker "
onchange = " validate_date(this); " >
< / b > < / span >
& nbsp ;
( nombre de < em > demi - journées < / em > )
< / form > """
+ """
< script >
function validate_date ( el ) {
const regex = / ^ [ 0 - 3 ] ? [ 0 - 9 ] \/ [ 0 - 9 ] { 1 , 2 } \/ [ 0 - 9 ] { 1 , 4 } $ / ;
if ( regex . test ( el . value ) ) {
return el . form . submit ( ) ;
}
return false ;
}
< / script >
"""
)
2021-06-02 22:40:34 +02:00
tab = GenTable (
columns_ids = columns_ids ,
rows = T ,
2021-07-28 17:03:54 +02:00
preferences = sco_preferences . SemPreferences ( formsemestre_id ) ,
2021-06-02 22:40:34 +02:00
titles = {
" etatincursem " : " Etat " ,
" nomprenom " : " Nom " ,
" nbabsjust " : " Justifiées " ,
" nbabsnonjust " : " Non justifiées " ,
" nbabs " : " Total " ,
" nbjustifs_noabs " : " Justifs non utilisés " ,
" boursier " : " Bourse " ,
} ,
html_sortable = True ,
html_class = " table_leftalign " ,
2021-06-13 18:29:53 +02:00
html_header = html_sco_header . sco_header (
2021-06-02 22:40:34 +02:00
page_title = title ,
init_qtip = True ,
javascripts = [ " js/etud_info.js " ] ,
) ,
2022-05-03 02:24:09 +02:00
html_title = html_sco_header . html_sem_header ( title , with_page_header = False )
+ form_date ,
# "<p>Période du %s au %s (nombre de <b>demi-journées</b>)<br/>" % (debut, fin),
2021-06-02 22:40:34 +02:00
base_url = " %s &formsemestre_id= %s &debut= %s &fin= %s "
% ( groups_infos . base_url , formsemestre_id , debut , fin ) ,
filename = " etat_abs_ "
+ scu . make_filename (
" %s de %s " % ( groups_infos . groups_filename , sem [ " titreannee " ] )
) ,
caption = title ,
html_next_section = """ </table>
< p class = " help " >
Justifs non utilisés : nombre de demi - journées avec justificatif mais sans absences relevées .
< / p >
< p class = " help " >
Cliquez sur un nom pour afficher le calendrier des absences < br / >
ou entrez une date pour visualiser les absents un jour donné & nbsp ; :
< / p >
< div style = " margin-bottom: 10px; " >
< form action = " EtatAbsencesDate " method = " get " action = " %s " >
< input type = " hidden " name = " formsemestre_id " value = " %s " >
% s
< input type = " text " name = " date " size = " 10 " class = " datepicker " / >
< input type = " submit " name = " " value = " visualiser les absences " >
< / form > < / div >
"""
2021-09-18 10:10:02 +02:00
% ( request . base_url , formsemestre_id , groups_infos . get_form_elem ( ) ) ,
2021-06-02 22:40:34 +02:00
)
2021-09-16 00:15:10 +02:00
return tab . make_page ( format = format )
2021-06-02 22:40:34 +02:00
@bp.route ( " /EtatAbsencesDate " )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoView )
2021-08-21 00:24:51 +02:00
@scodoc7func
2021-09-08 00:34:45 +02:00
def EtatAbsencesDate ( group_ids = [ ] , date = None ) : # list of groups to display
2021-06-02 22:40:34 +02:00
# ported from dtml
""" Etat des absences pour un groupe à une date donnée """
# Informations sur les groupes à afficher:
2021-09-08 00:34:45 +02:00
groups_infos = sco_groups_view . DisplayedGroupsInfos ( group_ids )
2021-07-29 16:58:18 +02:00
H = [ html_sco_header . sco_header ( page_title = " Etat des absences " ) ]
2021-06-02 22:40:34 +02:00
if date :
2021-06-15 13:59:56 +02:00
dateiso = ndb . DateDMYtoISO ( date )
2021-06-02 22:40:34 +02:00
nbetud = 0
t_nbabsjustam = 0
t_nbabsam = 0
t_nbabsjustpm = 0
t_nbabspm = 0
H . append ( " <h2>État des absences le %s </h2> " % date )
H . append (
""" <table border= " 0 " cellspacing= " 4 " cellpadding= " 0 " >
< tr > < th > & nbsp ; < / th >
< th style = " width: 10em; " > Matin < / th > < th style = " width: 10em; " > Après - midi < / th > < / tr >
"""
)
for etud in groups_infos . members :
2021-07-19 19:53:01 +02:00
nbabsam = sco_abs . count_abs (
etudid = etud [ " etudid " ] , debut = dateiso , fin = dateiso , matin = 1
2021-06-02 22:40:34 +02:00
)
2021-07-19 19:53:01 +02:00
nbabspm = sco_abs . count_abs (
etudid = etud [ " etudid " ] , debut = dateiso , fin = dateiso , matin = 0
2021-06-02 22:40:34 +02:00
)
if ( nbabsam != 0 ) or ( nbabspm != 0 ) :
nbetud + = 1
2021-07-19 19:53:01 +02:00
nbabsjustam = sco_abs . count_abs_just (
etudid = etud [ " etudid " ] , debut = dateiso , fin = dateiso , matin = 1
2021-06-02 22:40:34 +02:00
)
2021-07-19 19:53:01 +02:00
nbabsjustpm = sco_abs . count_abs_just (
etudid = etud [ " etudid " ] , debut = dateiso , fin = dateiso , matin = 0
2021-06-02 22:40:34 +02:00
)
H . append (
""" <tr bgcolor= " #FFFFFF " ><td>
< a href = " CalAbs?etudid= %(etudid)s " > < font color = " #A00000 " > % ( nomprenom ) s < / font > < / a > < / td > < td align = " center " > """
% etud
) # """
if nbabsam != 0 :
if nbabsjustam :
H . append ( " Just. " )
t_nbabsjustam + = 1
else :
H . append ( " Abs. " )
t_nbabsam + = 1
else :
H . append ( " " )
H . append ( ' </td><td align= " center " > ' )
if nbabspm != 0 :
if nbabsjustpm :
H . append ( " Just. " )
t_nbabsjustam + = 1
else :
H . append ( " Abs. " )
t_nbabspm + = 1
else :
H . append ( " " )
H . append ( " </td></tr> " )
H . append (
""" <tr bgcolor= " #FFFFFF " ><td></td><td> %d abs, %d just.</td><td> %d abs, %d just.</td></tr> """
% ( t_nbabsam , t_nbabsjustam , t_nbabspm , t_nbabsjustpm )
)
H . append ( " </table> " )
if nbetud == 0 :
H . append ( " <p>Aucune absence !</p> " )
else :
H . append (
""" <h2>Erreur: vous n ' avez pas choisi de date !</h2>
2021-06-21 23:13:57 +02:00
"""
2021-06-02 22:40:34 +02:00
)
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + html_sco_header . sco_footer ( )
2021-06-02 22:40:34 +02:00
# ----- Gestion des "billets d'absence": signalement par les etudiants eux mêmes (à travers le portail)
2021-10-24 12:01:42 +02:00
@bp.route ( " /AddBilletAbsence " , methods = [ " GET " , " POST " ] ) # API ScoDoc 7 compat
2021-10-26 00:13:42 +02:00
@scodoc
2021-10-28 00:52:23 +02:00
@permission_required_compat_scodoc7 ( Permission . ScoAbsAddBillet )
2021-08-21 00:24:51 +02:00
@scodoc7func
2021-06-02 22:40:34 +02:00
def AddBilletAbsence (
begin ,
end ,
description ,
etudid = False ,
code_nip = None ,
code_ine = None ,
justified = True ,
2021-11-01 16:59:56 +01:00
format = " json " ,
xml_reply = True , # deprecated
2021-06-02 22:40:34 +02:00
) :
2021-10-24 12:01:42 +02:00
""" Mémorise un " billet "
2021-06-02 22:40:34 +02:00
begin et end sont au format ISO ( eg " 1999-01-08 04:05:06 " )
"""
2022-08-01 21:42:19 +02:00
log ( " Warning: calling deprecated AddBilletAbsence " )
2021-10-07 23:21:30 +02:00
begin = str ( begin )
end = str ( end )
code_nip = str ( code_nip ) if code_nip else None
2022-08-01 21:42:19 +02:00
etud = api . tools . get_etud ( etudid = None , nip = None , ine = None )
2021-06-02 22:40:34 +02:00
# check dates
begin_date = dateutil . parser . isoparse ( begin ) # may raises ValueError
end_date = dateutil . parser . isoparse ( end )
if begin_date > end_date :
raise ValueError ( " invalid dates " )
#
2021-08-10 13:44:30 +02:00
justified = bool ( justified )
2021-11-01 16:59:56 +01:00
xml_reply = bool ( xml_reply )
if xml_reply : # backward compat
format = " xml "
2022-08-01 21:42:19 +02:00
#
billet = BilletAbsence (
etudid = etud . id ,
abs_begin = begin ,
abs_end = end ,
description = description ,
etat = False ,
justified = justified ,
)
db . session . add ( billet )
db . session . commit ( )
2021-11-01 16:59:56 +01:00
# Renvoie le nouveau billet au format demandé
2022-08-01 21:42:19 +02:00
table = sco_abs_billets . table_billets ( [ billet ] , etud = etud )
log ( f " AddBilletAbsence: new billet_id= { billet . id } " )
return table . make_page ( format = format )
2021-06-02 22:40:34 +02:00
2022-08-01 21:42:19 +02:00
@bp.route ( " /add_billets_absence_form " , methods = [ " GET " , " POST " ] )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoAbsAddBillet )
2021-08-21 00:24:51 +02:00
@scodoc7func
2022-08-01 21:42:19 +02:00
def add_billets_absence_form ( etudid ) :
""" Formulaire ajout billet (pour tests seulement, le vrai
formulaire accessible aux etudiants étant sur le portail étudiant ) .
2021-06-02 22:40:34 +02:00
"""
2021-08-22 13:24:36 +02:00
etud = sco_etud . get_etud_info ( filled = True , etudid = etudid ) [ 0 ]
2021-06-02 22:40:34 +02:00
H = [
2021-06-13 18:29:53 +02:00
html_sco_header . sco_header (
2021-07-29 16:31:15 +02:00
page_title = " Billet d ' absence de %s " % etud [ " nomprenom " ]
2021-06-02 22:40:34 +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 ( ) ,
2021-06-02 22:40:34 +02:00
(
( " etudid " , { " input_type " : " hidden " } ) ,
2022-01-10 12:00:02 +01:00
( " begin " , { " input_type " : " datedmy " } ) ,
( " end " , { " input_type " : " datedmy " } ) ,
2021-06-02 22:40:34 +02:00
(
" justified " ,
{ " input_type " : " boolcheckbox " , " default " : 0 , " title " : " Justifiée " } ,
) ,
( " description " , { " input_type " : " textarea " } ) ,
) ,
)
if tf [ 0 ] == 0 :
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + tf [ 1 ] + html_sco_header . sco_footer ( )
2021-06-02 22:40:34 +02:00
elif tf [ 0 ] == - 1 :
2021-07-31 18:01:10 +02:00
return flask . redirect ( scu . ScoURL ( ) )
2021-06-02 22:40:34 +02:00
else :
e = tf [ 2 ] [ " begin " ] . split ( " / " )
begin = e [ 2 ] + " - " + e [ 1 ] + " - " + e [ 0 ] + " 00:00:00 "
e = tf [ 2 ] [ " end " ] . split ( " / " )
end = e [ 2 ] + " - " + e [ 1 ] + " - " + e [ 0 ] + " 00:00:00 "
log (
2021-06-19 23:21:37 +02:00
AddBilletAbsence (
2021-06-02 22:40:34 +02:00
begin ,
end ,
tf [ 2 ] [ " description " ] ,
etudid = etudid ,
xml_reply = True ,
justified = tf [ 2 ] [ " justified " ] ,
)
)
2022-08-01 21:42:19 +02:00
return flask . redirect ( " billets_etud?etudid= " + str ( etudid ) )
2021-06-02 22:40:34 +02:00
2022-08-01 21:42:19 +02:00
@bp.route ( " /billets_etud/<int:etudid> " )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoView )
2022-08-01 21:42:19 +02:00
def billets_etud ( etudid = False ) :
2021-06-02 22:40:34 +02:00
""" Liste billets pour un etudiant """
2022-08-01 21:42:19 +02:00
fmt = request . args . get ( " format " , " html " )
if not fmt in { " html " , " json " , " xml " , " xls " , " xlsx " } :
return ScoValueError ( " Format invalide " )
table = sco_abs_billets . table_billets_etud ( etudid )
if table :
return table . make_page ( format = fmt )
return " "
2021-06-02 22:40:34 +02:00
2022-08-01 21:42:19 +02:00
# DEEPRECATED: pour compat anciens clients PHP
@bp.route ( " /XMLgetBilletsEtud " , methods = [ " GET " , " POST " ] )
2021-10-26 00:13:42 +02:00
@scodoc
2021-10-28 00:52:23 +02:00
@permission_required_compat_scodoc7 ( Permission . ScoView )
2021-08-21 00:24:51 +02:00
@scodoc7func
2021-09-21 15:53:33 +02:00
def XMLgetBilletsEtud ( etudid = False ) :
2021-06-02 22:40:34 +02:00
""" Liste billets pour un etudiant """
2022-08-01 21:42:19 +02:00
log ( " Warning: called deprecated XMLgetBilletsEtud " )
table = sco_abs_billets . table_billets_etud ( etudid )
if table :
return table . make_page ( format = " xml " )
return " "
2021-06-02 22:40:34 +02:00
2022-08-01 21:42:19 +02:00
@bp.route ( " /list_billets " , methods = [ " GET " ] )
2021-08-13 00:34:58 +02:00
@scodoc
2021-10-24 12:01:42 +02:00
@permission_required ( Permission . ScoView )
2021-08-21 00:24:51 +02:00
@scodoc7func
2022-08-01 21:42:19 +02:00
def list_billets ( ) :
""" Page liste des billets non traités pour tous les étudiants du département
et formulaire recherche d ' un billet.
"""
table = sco_abs_billets . table_billets_etud ( etat = False )
T = table . html ( )
2021-06-02 22:40:34 +02:00
H = [
2021-07-29 16:31:15 +02:00
html_sco_header . sco_header ( page_title = " Billet d ' absence non traités " ) ,
2022-08-01 21:42:19 +02:00
f " <h2>Billets d ' absence en attente de traitement ( { table . get_nb_rows ( ) } )</h2> " ,
2021-06-02 22:40:34 +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 ( ) ,
2021-06-02 22:40:34 +02:00
( ( " billet_id " , { " input_type " : " text " , " title " : " Numéro du billet " } ) , ) ,
submitbutton = False ,
)
if tf [ 0 ] == 0 :
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + tf [ 1 ] + T + html_sco_header . sco_footer ( )
2021-06-02 22:40:34 +02:00
else :
2021-07-31 18:01:10 +02:00
return flask . redirect (
2022-08-01 21:42:19 +02:00
url_for (
" absences.process_billet_absence_form " ,
billet_id = tf [ 2 ] [ " billet_id " ] ,
scodoc_dept = g . scodoc_dept ,
)
2021-06-02 22:40:34 +02:00
)
2022-08-01 21:42:19 +02:00
@bp.route ( " /delete_billets_absence " , methods = [ " POST " , " GET " ] )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoAbsChange )
2021-08-21 00:24:51 +02:00
@scodoc7func
2022-08-01 21:42:19 +02:00
def delete_billets_absence ( billet_id , dialog_confirmed = False ) :
2021-06-02 22:40:34 +02:00
""" Supprime un billet. """
2021-06-15 13:59:56 +02:00
cnx = ndb . GetDBConnexion ( )
2021-06-02 22:40:34 +02:00
billets = sco_abs . billet_absence_list ( cnx , { " billet_id " : billet_id } )
if not billets :
2021-07-31 18:01:10 +02:00
return flask . redirect (
2022-08-01 21:42:19 +02:00
" list_billets?head_message=Billet %% 20 %s %% 20inexistant ! " % billet_id
2021-06-02 22:40:34 +02:00
)
if not dialog_confirmed :
2022-08-01 21:42:19 +02:00
tab = sco_abs_billets . table_billets ( billets )
2021-06-21 12:13:25 +02:00
return scu . confirm_dialog (
2021-06-02 22:40:34 +02:00
""" <h2>Supprimer ce billet ?</h2> """ + tab . html ( ) ,
dest_url = " " ,
2022-08-01 21:42:19 +02:00
cancel_url = " list_billets " ,
2021-06-02 22:40:34 +02:00
parameters = { " billet_id " : billet_id } ,
)
sco_abs . billet_absence_delete ( cnx , billet_id )
2022-08-01 21:42:19 +02:00
return flask . redirect ( " list_billets?head_message=Billet %20s upprimé " )
2021-06-02 22:40:34 +02:00
2021-09-24 01:07:00 +02:00
def _ProcessBilletAbsence ( billet , estjust , description ) :
2021-06-02 22:40:34 +02:00
""" Traite un billet: ajoute absence(s) et éventuellement justificatifs,
et change l ' état du billet à 1.
NB : actuellement , les heures ne sont utilisées que pour déterminer si matin et / ou après - midi .
"""
2021-06-15 13:59:56 +02:00
cnx = ndb . GetDBConnexion ( )
2021-06-02 22:40:34 +02:00
if billet [ " etat " ] != 0 :
log ( " billet= %s " % billet )
log ( " billet deja traité ! " )
return - 1
n = 0 # nombre de demi-journées d'absence ajoutées
# 1-- ajout des absences (et justifs)
datedebut = billet [ " abs_begin " ] . strftime ( " %d / % m/ % Y " )
datefin = billet [ " abs_end " ] . strftime ( " %d / % m/ % Y " )
2021-08-21 00:24:51 +02:00
dates = sco_abs . DateRangeISO ( datedebut , datefin )
2021-06-02 22:40:34 +02:00
# commence après-midi ?
if dates and billet [ " abs_begin " ] . hour > 11 :
2021-06-19 23:21:37 +02:00
sco_abs . add_absence (
billet [ " etudid " ] ,
dates [ 0 ] ,
0 ,
estjust ,
description = description ,
2021-06-02 22:40:34 +02:00
)
n + = 1
dates = dates [ 1 : ]
# termine matin ?
if dates and billet [ " abs_end " ] . hour < 12 :
2021-06-19 23:21:37 +02:00
sco_abs . add_absence (
2021-06-02 22:40:34 +02:00
billet [ " etudid " ] ,
dates [ - 1 ] ,
1 ,
estjust ,
description = description ,
)
n + = 1
dates = dates [ : - 1 ]
for jour in dates :
2021-06-19 23:21:37 +02:00
sco_abs . add_absence (
billet [ " etudid " ] ,
jour ,
0 ,
estjust ,
description = description ,
2021-06-02 22:40:34 +02:00
)
2021-06-19 23:21:37 +02:00
sco_abs . add_absence (
billet [ " etudid " ] ,
jour ,
1 ,
estjust ,
description = description ,
2021-06-02 22:40:34 +02:00
)
n + = 2
# 2- change etat du billet
sco_abs . billet_absence_edit ( cnx , { " billet_id " : billet [ " billet_id " ] , " etat " : 1 } )
return n
2022-08-01 21:42:19 +02:00
@bp.route ( " /process_billet_absence_form " , methods = [ " POST " , " GET " ] )
2021-08-13 00:34:58 +02:00
@scodoc
2021-06-02 22:40:34 +02:00
@permission_required ( Permission . ScoAbsChange )
2021-08-21 00:24:51 +02:00
@scodoc7func
2022-08-01 21:42:19 +02:00
def process_billet_absence_form ( billet_id ) :
2021-06-02 22:40:34 +02:00
""" Formulaire traitement d ' un billet """
2021-06-15 13:59:56 +02:00
cnx = ndb . GetDBConnexion ( )
2021-06-02 22:40:34 +02:00
billets = sco_abs . billet_absence_list ( cnx , { " billet_id " : billet_id } )
if not billets :
2021-07-31 18:01:10 +02:00
return flask . redirect (
2022-08-01 21:42:19 +02:00
" list_billets?head_message=Billet %% 20 %s %% 20inexistant ! " % billet_id
2021-06-02 22:40:34 +02:00
)
billet = billets [ 0 ]
etudid = billet [ " etudid " ]
2021-08-22 13:24:36 +02:00
etud = sco_etud . get_etud_info ( filled = True , etudid = etudid ) [ 0 ]
2021-06-02 22:40:34 +02:00
H = [
2021-06-13 18:29:53 +02:00
html_sco_header . sco_header (
2021-06-02 22:40:34 +02:00
page_title = " Traitement billet d ' absence de %s " % etud [ " nomprenom " ] ,
) ,
2021-07-11 17:37:12 +02:00
' <h2>Traitement du billet %s : <a class= " discretelink " href= " %s " > %s </a></h2> '
% (
billet_id ,
url_for ( " scolar.ficheEtud " , scodoc_dept = g . scodoc_dept , etudid = etudid ) ,
etud [ " nomprenom " ] ,
) ,
2021-06-02 22:40:34 +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 ( ) ,
2021-06-02 22:40:34 +02:00
(
( " billet_id " , { " input_type " : " hidden " } ) ,
(
" etudid " ,
{ " input_type " : " hidden " } ,
) , # pour centrer l'UI sur l'étudiant
(
" estjust " ,
{ " input_type " : " boolcheckbox " , " title " : " Absences justifiées " } ,
) ,
( " description " , { " input_type " : " text " , " size " : 42 , " title " : " Raison " } ) ,
) ,
initvalues = {
" description " : billet [ " description " ] ,
" estjust " : billet [ " justified " ] ,
" etudid " : etudid ,
} ,
submitlabel = " Enregistrer ces absences " ,
)
if tf [ 0 ] == 0 :
2022-08-01 21:42:19 +02:00
tab = sco_abs_billets . table_billets ( [ billet ] , etud = etud )
2021-06-02 22:40:34 +02:00
H . append ( tab . html ( ) )
2021-08-11 00:36:07 +02:00
if billet [ " justified " ] :
2021-06-02 22:40:34 +02:00
H . append (
""" <p>L ' étudiant pense pouvoir justifier cette absence.<br/><em>Vérifiez le justificatif avant d ' enregistrer.</em></p> """
)
F = (
2022-08-01 21:42:19 +02:00
""" <p><a class= " stdlink " href= " delete_billets_absence?billet_id= %s " >Supprimer ce billet</a> (utiliser en cas d ' erreur, par ex. billet en double)</p> """
2021-06-02 22:40:34 +02:00
% billet_id
)
2022-08-01 21:42:19 +02:00
F + = ' <p><a class= " stdlink " href= " list_billets " >Liste de tous les billets en attente</a></p> '
2021-06-02 22:40:34 +02:00
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + " <br/> " + tf [ 1 ] + F + html_sco_header . sco_footer ( )
2021-06-02 22:40:34 +02:00
elif tf [ 0 ] == - 1 :
2021-07-31 18:01:10 +02:00
return flask . redirect ( scu . ScoURL ( ) )
2021-06-02 22:40:34 +02:00
else :
2021-09-24 01:07:00 +02:00
n = _ProcessBilletAbsence ( billet , tf [ 2 ] [ " estjust " ] , tf [ 2 ] [ " description " ] )
2021-06-02 22:40:34 +02:00
if tf [ 2 ] [ " estjust " ] :
j = " justifiées "
else :
j = " non justifiées "
H . append ( ' <div class= " head_message " > ' )
if n > 0 :
H . append ( " %d absences (1/2 journées) %s ajoutées " % ( n , j ) )
elif n == 0 :
H . append ( " Aucun jour d ' absence dans les dates indiquées ! " )
elif n < 0 :
H . append ( " Ce billet avait déjà été traité ! " )
H . append (
2022-08-01 21:42:19 +02:00
' </div><p><a class= " stdlink " href= " list_billets " >Autre billets en attente</a></p><h4>Billets déclarés par %s </h4> '
2021-06-02 22:40:34 +02:00
% ( etud [ " nomprenom " ] )
)
billets = sco_abs . billet_absence_list ( cnx , { " etudid " : etud [ " etudid " ] } )
2022-08-01 21:42:19 +02:00
tab = sco_abs_billets . table_billets ( billets , etud = etud )
2021-06-02 22:40:34 +02:00
H . append ( tab . html ( ) )
2021-07-29 10:19:00 +02:00
return " \n " . join ( H ) + html_sco_header . sco_footer ( )
2021-06-02 22:40:34 +02:00
2021-09-09 16:11:05 +02:00
# @bp.route("/essai_api7")
2021-10-26 00:13:42 +02:00
# @scodoc
2021-10-28 00:52:23 +02:00
# @permission_required_compat_scodoc7(Permission.ScoView)
2021-09-09 16:11:05 +02:00
# @scodoc7func
# def essai_api7(x="xxx"):
# "un essai"
# log("arfffffffffffffffffff")
# return "OK OK x=" + str(x)
2021-09-10 22:03:52 +02:00
@bp.route ( " /XMLgetAbsEtud " , methods = [ " GET " , " POST " ] ) # pour compat anciens clients PHP
2021-10-26 00:13:42 +02:00
@scodoc
2021-10-28 00:52:23 +02:00
@permission_required_compat_scodoc7 ( Permission . ScoView )
2021-08-21 00:24:51 +02:00
@scodoc7func
2021-09-24 12:10:53 +02:00
def XMLgetAbsEtud ( beg_date = " " , end_date = " " ) :
2021-06-02 22:40:34 +02:00
""" returns list of absences in date interval """
t0 = time . time ( )
2021-09-13 09:55:49 +02:00
etuds = sco_etud . get_etud_info ( filled = False )
if not etuds :
raise APIInvalidParams ( " étudiant inconnu " )
# raise ScoValueError("étudiant inconnu")
etud = etuds [ 0 ]
2021-06-02 22:40:34 +02:00
exp = re . compile ( r " ^( \ d {4} ) \ D?(0[1-9]|1[0-2]) \ D?([12] \ d|0[1-9]|3[01])$ " )
if not exp . match ( beg_date ) :
raise ScoValueError ( " invalid date: %s " % beg_date )
if not exp . match ( end_date ) :
raise ScoValueError ( " invalid date: %s " % end_date )
2021-09-12 23:06:23 +02:00
abs_list = sco_abs . list_abs_date ( etud [ " etudid " ] , beg_date , end_date )
2021-06-02 22:40:34 +02:00
2021-07-11 13:03:13 +02:00
doc = ElementTree . Element (
2021-09-11 21:54:53 +02:00
" absences " , etudid = str ( etud [ " etudid " ] ) , beg_date = beg_date , end_date = end_date
2021-07-11 13:03:13 +02:00
)
2021-09-12 23:06:23 +02:00
for a in abs_list :
2021-06-02 22:40:34 +02:00
if a [ " estabs " ] : # ne donne pas les justifications si pas d'absence
2021-07-11 13:03:13 +02:00
doc . append (
ElementTree . Element (
" abs " ,
begin = a [ " begin " ] ,
end = a [ " end " ] ,
description = a [ " description " ] ,
2021-09-13 09:55:49 +02:00
justified = str ( int ( a [ " estjust " ] ) ) ,
2021-07-11 13:03:13 +02:00
)
2021-06-02 22:40:34 +02:00
)
log ( " XMLgetAbsEtud ( %g s) " % ( time . time ( ) - t0 ) )
2021-09-24 12:10:53 +02:00
data = sco_xml . XML_HEADER + ElementTree . tostring ( doc ) . decode ( scu . SCO_ENCODING )
2021-09-25 12:35:26 +02:00
return scu . send_file ( data , mime = scu . XML_MIMETYPE , attached = False )