forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -66,7 +66,6 @@ def get_model_api_object(model_cls: db.Model, model_id: int, join_cls: db.Model
|
|||||||
|
|
||||||
from app.api import tokens
|
from app.api import tokens
|
||||||
from app.api import (
|
from app.api import (
|
||||||
absences,
|
|
||||||
assiduites,
|
assiduites,
|
||||||
billets_absences,
|
billets_absences,
|
||||||
departements,
|
departements,
|
||||||
|
@ -1,263 +0,0 @@
|
|||||||
##############################################################################
|
|
||||||
# ScoDoc
|
|
||||||
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
|
||||||
# See LICENSE
|
|
||||||
##############################################################################
|
|
||||||
"""ScoDoc 9 API : Absences
|
|
||||||
"""
|
|
||||||
|
|
||||||
from flask_json import as_json
|
|
||||||
|
|
||||||
from app import db
|
|
||||||
from app.api import api_bp as bp, API_CLIENT_ERROR
|
|
||||||
from app.scodoc.sco_utils import json_error
|
|
||||||
from app.decorators import scodoc, permission_required
|
|
||||||
from app.models import Identite
|
|
||||||
|
|
||||||
from app.scodoc import notesdb as ndb
|
|
||||||
from app.scodoc import sco_abs
|
|
||||||
|
|
||||||
from app.scodoc.sco_groups import get_group_members
|
|
||||||
from app.scodoc.sco_permissions import Permission
|
|
||||||
|
|
||||||
|
|
||||||
# TODO XXX revoir routes web API et calcul des droits
|
|
||||||
@bp.route("/absences/etudid/<int:etudid>", methods=["GET"])
|
|
||||||
@scodoc
|
|
||||||
@permission_required(Permission.ScoView)
|
|
||||||
@as_json
|
|
||||||
def absences(etudid: int = None):
|
|
||||||
"""
|
|
||||||
Liste des absences de cet étudiant
|
|
||||||
|
|
||||||
Exemple de résultat:
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"jour": "2022-04-15",
|
|
||||||
"matin": true,
|
|
||||||
"estabs": true,
|
|
||||||
"estjust": true,
|
|
||||||
"description": "",
|
|
||||||
"begin": "2022-04-15 08:00:00",
|
|
||||||
"end": "2022-04-15 11:59:59"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jour": "2022-04-15",
|
|
||||||
"matin": false,
|
|
||||||
"estabs": true,
|
|
||||||
"estjust": false,
|
|
||||||
"description": "",
|
|
||||||
"begin": "2022-04-15 12:00:00",
|
|
||||||
"end": "2022-04-15 17:59:59"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
etud = db.session.get(Identite, etudid)
|
|
||||||
if etud is None:
|
|
||||||
return json_error(404, message="etudiant inexistant")
|
|
||||||
# Absences de l'étudiant
|
|
||||||
ndb.open_db_connection()
|
|
||||||
abs_list = sco_abs.list_abs_date(etud.id)
|
|
||||||
for absence in abs_list:
|
|
||||||
absence["jour"] = absence["jour"].isoformat()
|
|
||||||
return abs_list
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/absences/etudid/<int:etudid>/just", methods=["GET"])
|
|
||||||
@scodoc
|
|
||||||
@permission_required(Permission.ScoView)
|
|
||||||
@as_json
|
|
||||||
def absences_just(etudid: int = None):
|
|
||||||
"""
|
|
||||||
Retourne la liste des absences justifiées d'un étudiant donné
|
|
||||||
|
|
||||||
etudid : l'etudid d'un étudiant
|
|
||||||
nip: le code nip d'un étudiant
|
|
||||||
ine : le code ine d'un étudiant
|
|
||||||
|
|
||||||
Exemple de résultat :
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"jour": "2022-04-15",
|
|
||||||
"matin": true,
|
|
||||||
"estabs": true,
|
|
||||||
"estjust": true,
|
|
||||||
"description": "",
|
|
||||||
"begin": "2022-04-15 08:00:00",
|
|
||||||
"end": "2022-04-15 11:59:59"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jour": "Fri, 15 Apr 2022 00:00:00 GMT",
|
|
||||||
"matin": false,
|
|
||||||
"estabs": true,
|
|
||||||
"estjust": true,
|
|
||||||
"description": "",
|
|
||||||
"begin": "2022-04-15 12:00:00",
|
|
||||||
"end": "2022-04-15 17:59:59"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
etud = db.session.get(Identite, etudid)
|
|
||||||
if etud is None:
|
|
||||||
return json_error(404, message="etudiant inexistant")
|
|
||||||
|
|
||||||
# Absences justifiées de l'étudiant
|
|
||||||
abs_just = [
|
|
||||||
absence for absence in sco_abs.list_abs_date(etud.id) if absence["estjust"]
|
|
||||||
]
|
|
||||||
for absence in abs_just:
|
|
||||||
absence["jour"] = absence["jour"].isoformat()
|
|
||||||
return abs_just
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route(
|
|
||||||
"/absences/abs_group_etat/<int:group_id>",
|
|
||||||
methods=["GET"],
|
|
||||||
)
|
|
||||||
@bp.route(
|
|
||||||
"/absences/abs_group_etat/group_id/<int:group_id>/date_debut/<string:date_debut>/date_fin/<string:date_fin>",
|
|
||||||
methods=["GET"],
|
|
||||||
)
|
|
||||||
@scodoc
|
|
||||||
@permission_required(Permission.ScoView)
|
|
||||||
@as_json
|
|
||||||
def abs_groupe_etat(group_id: int, date_debut=None, date_fin=None):
|
|
||||||
"""
|
|
||||||
Liste des absences d'un groupe (possibilité de choisir entre deux dates)
|
|
||||||
|
|
||||||
group_id = l'id du groupe
|
|
||||||
date_debut = None par défaut, sinon la date ISO du début de notre filtre
|
|
||||||
date_fin = None par défaut, sinon la date ISO de la fin de notre filtre
|
|
||||||
|
|
||||||
Exemple de résultat :
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"etudid": 1,
|
|
||||||
"list_abs": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"etudid": 2,
|
|
||||||
"list_abs": [
|
|
||||||
{
|
|
||||||
"jour": "Fri, 15 Apr 2022 00:00:00 GMT",
|
|
||||||
"matin": true,
|
|
||||||
"estabs": true,
|
|
||||||
"estjust": true,
|
|
||||||
"description": "",
|
|
||||||
"begin": "2022-04-15 08:00:00",
|
|
||||||
"end": "2022-04-15 11:59:59"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"jour": "Fri, 15 Apr 2022 00:00:00 GMT",
|
|
||||||
"matin": false,
|
|
||||||
"estabs": true,
|
|
||||||
"estjust": false,
|
|
||||||
"description": "",
|
|
||||||
"begin": "2022-04-15 12:00:00",
|
|
||||||
"end": "2022-04-15 17:59:59"
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
members = get_group_members(group_id)
|
|
||||||
|
|
||||||
data = []
|
|
||||||
# Filtre entre les deux dates renseignées
|
|
||||||
for member in members:
|
|
||||||
absence = {
|
|
||||||
"etudid": member["etudid"],
|
|
||||||
"list_abs": sco_abs.list_abs_date(member["etudid"], date_debut, date_fin),
|
|
||||||
}
|
|
||||||
data.append(absence)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
# XXX TODO EV: A REVOIR (data json dans le POST + modifier les routes)
|
|
||||||
# @bp.route(
|
|
||||||
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs",
|
|
||||||
# methods=["POST"],
|
|
||||||
# defaults={"just_or_not": 0},
|
|
||||||
# )
|
|
||||||
# @bp.route(
|
|
||||||
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_not_just",
|
|
||||||
# methods=["POST"],
|
|
||||||
# defaults={"just_or_not": 1},
|
|
||||||
# )
|
|
||||||
# @bp.route(
|
|
||||||
# "/absences/etudid/<int:etudid>/list_abs/<string:list_abs>/reset_etud_abs/only_just",
|
|
||||||
# methods=["POST"],
|
|
||||||
# defaults={"just_or_not": 2},
|
|
||||||
# )
|
|
||||||
# @token_auth.login_required
|
|
||||||
# @token_permission_required(Permission.APIAbsChange)
|
|
||||||
# def reset_etud_abs(etudid: int, list_abs: str, just_or_not: int = 0):
|
|
||||||
# """
|
|
||||||
# Set la liste des absences d'un étudiant sur tout un semestre.
|
|
||||||
# (les absences existant pour cet étudiant sur cette période sont effacées)
|
|
||||||
|
|
||||||
# etudid : l'id d'un étudiant
|
|
||||||
# list_abs : json d'absences
|
|
||||||
# just_or_not : 0 (pour les absences justifiées et non justifiées),
|
|
||||||
# 1 (pour les absences justifiées),
|
|
||||||
# 2 (pour les absences non justifiées)
|
|
||||||
# """
|
|
||||||
# # Toutes les absences
|
|
||||||
# if just_or_not == 0:
|
|
||||||
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
|
||||||
# for abs in list_abs:
|
|
||||||
# # Récupération de la date au format iso
|
|
||||||
# jour = abs["jour"].isoformat()
|
|
||||||
# if abs["matin"] is True:
|
|
||||||
# annule_absence(etudid, jour, True)
|
|
||||||
# annule_justif(etudid, jour, True)
|
|
||||||
# else:
|
|
||||||
# annule_absence(etudid, jour, False)
|
|
||||||
# annule_justif(etudid, jour, False)
|
|
||||||
|
|
||||||
# # Ajout de la liste d'absences en base
|
|
||||||
# add_abslist(list_abs)
|
|
||||||
|
|
||||||
# # Uniquement les absences justifiées
|
|
||||||
# elif just_or_not == 1:
|
|
||||||
# list_abs_not_just = []
|
|
||||||
# # Trie des absences justifiées
|
|
||||||
# for abs in list_abs:
|
|
||||||
# if abs["estjust"] is False:
|
|
||||||
# list_abs_not_just.append(abs)
|
|
||||||
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
|
||||||
# for abs in list_abs:
|
|
||||||
# # Récupération de la date au format iso
|
|
||||||
# jour = abs["jour"].isoformat()
|
|
||||||
# if abs["matin"] is True:
|
|
||||||
# annule_absence(etudid, jour, True)
|
|
||||||
# annule_justif(etudid, jour, True)
|
|
||||||
# else:
|
|
||||||
# annule_absence(etudid, jour, False)
|
|
||||||
# annule_justif(etudid, jour, False)
|
|
||||||
|
|
||||||
# # Ajout de la liste d'absences en base
|
|
||||||
# add_abslist(list_abs_not_just)
|
|
||||||
|
|
||||||
# # Uniquement les absences non justifiées
|
|
||||||
# elif just_or_not == 2:
|
|
||||||
# list_abs_just = []
|
|
||||||
# # Trie des absences non justifiées
|
|
||||||
# for abs in list_abs:
|
|
||||||
# if abs["estjust"] is True:
|
|
||||||
# list_abs_just.append(abs)
|
|
||||||
# # suppression des absences et justificatif déjà existant pour éviter les doublons
|
|
||||||
# for abs in list_abs:
|
|
||||||
# # Récupération de la date au format iso
|
|
||||||
# jour = abs["jour"].isoformat()
|
|
||||||
# if abs["matin"] is True:
|
|
||||||
# annule_absence(etudid, jour, True)
|
|
||||||
# annule_justif(etudid, jour, True)
|
|
||||||
# else:
|
|
||||||
# annule_absence(etudid, jour, False)
|
|
||||||
# annule_justif(etudid, jour, False)
|
|
||||||
|
|
||||||
# # Ajout de la liste d'absences en base
|
|
||||||
# add_abslist(list_abs_just)
|
|
File diff suppressed because it is too large
Load Diff
@ -364,7 +364,7 @@ def get_all_justified(
|
|||||||
|
|
||||||
|
|
||||||
# Gestion du cache
|
# Gestion du cache
|
||||||
def get_assiduites_count(etudid, sem):
|
def get_assiduites_count(etudid: int, sem: dict) -> tuple[int, int]:
|
||||||
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
||||||
tuple (nb abs non justifiées, nb abs justifiées)
|
tuple (nb abs non justifiées, nb abs justifiées)
|
||||||
Utilise un cache.
|
Utilise un cache.
|
||||||
@ -378,25 +378,43 @@ def get_assiduites_count(etudid, sem):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def formsemestre_get_assiduites_count(
|
||||||
|
etudid: int, formsemestre: FormSemestre
|
||||||
|
) -> tuple[int, int]:
|
||||||
|
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
||||||
|
tuple (nb abs non justifiées, nb abs justifiées)
|
||||||
|
Utilise un cache.
|
||||||
|
"""
|
||||||
|
metrique = sco_preferences.get_preference("assi_metrique", formsemestre.id)
|
||||||
|
return get_assiduites_count_in_interval(
|
||||||
|
etudid,
|
||||||
|
date_debut=formsemestre.date_debut,
|
||||||
|
date_fin=formsemestre.date_fin,
|
||||||
|
metrique=scu.translate_assiduites_metric(metrique),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_assiduites_count_in_interval(
|
def get_assiduites_count_in_interval(
|
||||||
etudid, date_debut_iso, date_fin_iso, metrique="demi"
|
etudid,
|
||||||
|
date_debut_iso: str = "",
|
||||||
|
date_fin_iso: str = "",
|
||||||
|
metrique="demi",
|
||||||
|
date_debut: datetime = None,
|
||||||
|
date_fin: datetime = None,
|
||||||
):
|
):
|
||||||
"""Les comptes d'absences de cet étudiant entre ces deux dates, incluses:
|
"""Les comptes d'absences de cet étudiant entre ces deux dates, incluses:
|
||||||
tuple (nb abs, nb abs justifiées)
|
tuple (nb abs, nb abs justifiées)
|
||||||
|
On peut spécifier les dates comme datetime ou iso.
|
||||||
Utilise un cache.
|
Utilise un cache.
|
||||||
"""
|
"""
|
||||||
key = (
|
date_debut_iso = date_debut_iso or date_debut.isoformat()
|
||||||
str(etudid)
|
date_fin_iso = date_fin_iso or date_fin.isoformat()
|
||||||
+ "_"
|
key = f"{etudid}_{date_debut_iso}_{date_fin_iso}{metrique}_assiduites"
|
||||||
+ date_debut_iso
|
|
||||||
+ "_"
|
|
||||||
+ date_fin_iso
|
|
||||||
+ f"{metrique}_assiduites"
|
|
||||||
)
|
|
||||||
r = sco_cache.AbsSemEtudCache.get(key)
|
r = sco_cache.AbsSemEtudCache.get(key)
|
||||||
if not r:
|
if not r:
|
||||||
date_debut: datetime.datetime = scu.is_iso_formated(date_debut_iso, True)
|
date_debut: datetime = date_debut or datetime.fromisoformat(date_debut_iso)
|
||||||
date_fin: datetime.datetime = scu.is_iso_formated(date_fin_iso, True)
|
date_fin: datetime = date_fin or datetime.fromisoformat(date_fin_iso)
|
||||||
|
|
||||||
assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid)
|
assiduites: Assiduite = Assiduite.query.filter_by(etudid=etudid)
|
||||||
assiduites = assiduites.filter(Assiduite.etat == scu.EtatAssiduite.ABSENT)
|
assiduites = assiduites.filter(Assiduite.etat == scu.EtatAssiduite.ABSENT)
|
||||||
|
@ -58,14 +58,12 @@ from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
|||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import htmlutils
|
from app.scodoc import htmlutils
|
||||||
from app.scodoc import sco_assiduites
|
from app.scodoc import sco_assiduites
|
||||||
from app.scodoc import sco_abs_views
|
|
||||||
from app.scodoc import sco_bulletins_generator
|
from app.scodoc import sco_bulletins_generator
|
||||||
from app.scodoc import sco_bulletins_json
|
from app.scodoc import sco_bulletins_json
|
||||||
from app.scodoc import sco_bulletins_pdf
|
from app.scodoc import sco_bulletins_pdf
|
||||||
from app.scodoc import sco_bulletins_xml
|
from app.scodoc import sco_bulletins_xml
|
||||||
from app.scodoc import codes_cursus
|
from app.scodoc import codes_cursus
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_evaluation_db
|
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
@ -1116,9 +1114,10 @@ def mail_bulletin(formsemestre_id, infos, pdfdata, filename, recipient_addr):
|
|||||||
hea = ""
|
hea = ""
|
||||||
|
|
||||||
if sco_preferences.get_preference("bul_mail_list_abs"):
|
if sco_preferences.get_preference("bul_mail_list_abs"):
|
||||||
hea += "\n\n" + sco_abs_views.ListeAbsEtud(
|
hea += "\n\n" + "(LISTE D'ABSENCES NON DISPONIBLE)" # XXX TODO-ASSIDUITE
|
||||||
etud["etudid"], with_evals=False, format="text"
|
# sco_abs_views.ListeAbsEtud(
|
||||||
)
|
# etud["etudid"], with_evals=False, format="text"
|
||||||
|
# )
|
||||||
|
|
||||||
subject = f"""Relevé de notes de {etud["nomprenom"]}"""
|
subject = f"""Relevé de notes de {etud["nomprenom"]}"""
|
||||||
recipients = [recipient_addr]
|
recipients = [recipient_addr]
|
||||||
|
@ -132,10 +132,13 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
|||||||
if sco_preferences.get_preference(
|
if sco_preferences.get_preference(
|
||||||
"bul_show_minmax_mod", formsemestre_id
|
"bul_show_minmax_mod", formsemestre_id
|
||||||
):
|
):
|
||||||
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
|
rang_minmax = (
|
||||||
mod["mod_rang_txt"],
|
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
|
||||||
scu.fmt_note(mod["stats"]["min"]),
|
% (
|
||||||
scu.fmt_note(mod["stats"]["max"]),
|
mod["mod_rang_txt"],
|
||||||
|
scu.fmt_note(mod["stats"]["min"]),
|
||||||
|
scu.fmt_note(mod["stats"]["max"]),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
|
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
|
||||||
@ -301,9 +304,11 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
|||||||
authuser = self.authuser
|
authuser = self.authuser
|
||||||
H = []
|
H = []
|
||||||
# --- Absences
|
# --- Absences
|
||||||
|
# XXX TODO-ASSIDUITE
|
||||||
|
# au passage, utiliser url_for...
|
||||||
H.append(
|
H.append(
|
||||||
"""<p>
|
"""<p>
|
||||||
<a href="../Absences/CalAbs?etudid=%(etudid)s" class="bull_link">
|
XXX <a href="../Absences/CalAbs?etudid=%(etudid)s" class="bull_link">
|
||||||
<b>Absences :</b> %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
|
<b>Absences :</b> %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
|
||||||
(pendant ce semestre).
|
(pendant ce semestre).
|
||||||
</a></p>
|
</a></p>
|
||||||
|
@ -124,9 +124,12 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
|
|||||||
nbabs = self.infos["nbabs"]
|
nbabs = self.infos["nbabs"]
|
||||||
story.append(Spacer(1, 2 * mm))
|
story.append(Spacer(1, 2 * mm))
|
||||||
if nbabs:
|
if nbabs:
|
||||||
|
# XXX TODO-ASSIDUITE
|
||||||
|
# et utiliser url_for...
|
||||||
H.append(
|
H.append(
|
||||||
"""<p class="bul_abs">
|
"""<p class="bul_abs">
|
||||||
<a href="../Absences/CalAbs?etudid=%(etudid)s" class="bull_link">
|
<a href="../Absences/CalAbs?etudid=%(etudid)s" class="bull_link">
|
||||||
|
XXX
|
||||||
<b>Absences :</b> %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
|
<b>Absences :</b> %(nbabs)s demi-journées, dont %(nbabsjust)s justifiées
|
||||||
(pendant ce semestre).
|
(pendant ce semestre).
|
||||||
</a></p>
|
</a></p>
|
||||||
|
@ -30,18 +30,16 @@
|
|||||||
from flask import url_for, g
|
from flask import url_for, g
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app.models import Evaluation, Identite
|
from app.models import Evaluation, FormSemestre, Identite
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_abs
|
|
||||||
from app.scodoc import sco_etud
|
|
||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_moduleimpl
|
|
||||||
|
|
||||||
|
|
||||||
|
# XXX TODO-ASSIDUITE https://scodoc.org/git/ScoDoc/ScoDoc/issues/685
|
||||||
def evaluation_check_absences(evaluation: Evaluation):
|
def evaluation_check_absences(evaluation: Evaluation):
|
||||||
"""Vérifie les absences au moment de cette évaluation.
|
"""Vérifie les absences au moment de cette évaluation.
|
||||||
Cas incohérents que l'on peut rencontrer pour chaque étudiant:
|
Cas incohérents que l'on peut rencontrer pour chaque étudiant:
|
||||||
@ -52,6 +50,8 @@ def evaluation_check_absences(evaluation: Evaluation):
|
|||||||
EXC et pas justifie
|
EXC et pas justifie
|
||||||
Ramene 5 listes d'etudid
|
Ramene 5 listes d'etudid
|
||||||
"""
|
"""
|
||||||
|
raise ScoValueError("Fonction non disponible, patience !") # XXX TODO-ASSIDUITE
|
||||||
|
|
||||||
if not evaluation.date_debut:
|
if not evaluation.date_debut:
|
||||||
return [], [], [], [], [] # evaluation sans date
|
return [], [], [], [], [] # evaluation sans date
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ def evaluation_check_absences_html(evaluation_id, with_header=True, show_ok=True
|
|||||||
)
|
)
|
||||||
if linkabs:
|
if linkabs:
|
||||||
url = url_for(
|
url = url_for(
|
||||||
"absences.doSignaleAbsence",
|
"absences.doSignaleAbsence", # XXX TODO-ASSIDUITE
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
etudid=etudid,
|
etudid=etudid,
|
||||||
# par defaut signale le jour du début de l'éval
|
# par defaut signale le jour du début de l'éval
|
||||||
@ -221,7 +221,9 @@ def evaluation_check_absences_html(evaluation_id, with_header=True, show_ok=True
|
|||||||
|
|
||||||
def formsemestre_check_absences_html(formsemestre_id):
|
def formsemestre_check_absences_html(formsemestre_id):
|
||||||
"""Affiche etat verification absences pour toutes les evaluations du semestre !"""
|
"""Affiche etat verification absences pour toutes les evaluations du semestre !"""
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
formsemestre: FormSemestre = FormSemestre.query.filter_by(
|
||||||
|
dept_id=g.scodoc_dept_id, id=formsemestre_id
|
||||||
|
).first_or_404()
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.html_sem_header(
|
html_sco_header.html_sem_header(
|
||||||
"Vérification absences aux évaluations de ce semestre",
|
"Vérification absences aux évaluations de ce semestre",
|
||||||
@ -232,29 +234,27 @@ def formsemestre_check_absences_html(formsemestre_id):
|
|||||||
</p>""",
|
</p>""",
|
||||||
]
|
]
|
||||||
# Modules, dans l'ordre
|
# Modules, dans l'ordre
|
||||||
Mlist = sco_moduleimpl.moduleimpl_withmodule_list(formsemestre_id=formsemestre_id)
|
for modimpl in formsemestre.modimpls_sorted:
|
||||||
for M in Mlist:
|
if modimpl.evaluations.count() > 0:
|
||||||
evals = sco_evaluation_db.get_evaluation_dict(
|
|
||||||
{"moduleimpl_id": M["moduleimpl_id"]}
|
|
||||||
)
|
|
||||||
if evals:
|
|
||||||
H.append(
|
H.append(
|
||||||
'<div class="module_check_absences"><h2><a href="moduleimpl_status?moduleimpl_id=%s">%s: %s</a></h2>'
|
f"""<div class="module_check_absences">
|
||||||
% (
|
<h2><a href="{
|
||||||
M["moduleimpl_id"],
|
url_for("notes.moduleimpl_status",
|
||||||
M["module"]["code"] or "",
|
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
|
||||||
M["module"]["abbrev"] or "",
|
}">{modimpl.module.code or ""}: {modimpl.module.abbrev or ""}</a>
|
||||||
)
|
</h2>"""
|
||||||
)
|
)
|
||||||
for E in evals:
|
for evaluation in modimpl.evaluations.order_by(
|
||||||
H.append(
|
Evaluation.numero, Evaluation.date_debut
|
||||||
evaluation_check_absences_html(
|
):
|
||||||
E["evaluation_id"],
|
H.append(
|
||||||
with_header=False,
|
evaluation_check_absences_html(
|
||||||
show_ok=False,
|
evaluation.id, # XXX TODO-ASSIDUITE remplacer par evaluation ...
|
||||||
|
with_header=False,
|
||||||
|
show_ok=False,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
if evals:
|
|
||||||
H.append("</div>")
|
H.append("</div>")
|
||||||
|
|
||||||
H.append(html_sco_header.sco_footer())
|
H.append(html_sco_header.sco_footer())
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
@ -46,8 +46,8 @@ from app.scodoc.sco_utils import ModuleType
|
|||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
|
from app.scodoc import sco_cal
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_abs
|
|
||||||
from app.scodoc import sco_edit_module
|
from app.scodoc import sco_edit_module
|
||||||
from app.scodoc import sco_edit_ue
|
from app.scodoc import sco_edit_ue
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
@ -475,7 +475,7 @@ def formsemestre_evaluations_cal(formsemestre_id):
|
|||||||
if color == color_futur:
|
if color == color_futur:
|
||||||
event[2] = color_futur
|
event[2] = color_futur
|
||||||
|
|
||||||
cal_html = sco_abs.YearTable(
|
cal_html = sco_cal.YearTable(
|
||||||
year, events=list(events.values()), halfday=False, pad_width=None
|
year, events=list(events.values()), halfday=False, pad_width=None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -888,13 +888,14 @@ def _make_listes_sem(formsemestre: FormSemestre, with_absences=True):
|
|||||||
if n_members == 0:
|
if n_members == 0:
|
||||||
continue # skip empty groups
|
continue # skip empty groups
|
||||||
partition_is_empty = False
|
partition_is_empty = False
|
||||||
group["url_etat"] = url_for(
|
# XXX TODO-ASSIDUITE
|
||||||
"absences.EtatAbsencesGr",
|
group["url_etat"] = "non disponible" # url_for(
|
||||||
group_ids=group["group_id"],
|
# "absences.EtatAbsencesGr",
|
||||||
debut=formsemestre.date_debut.strftime("%d/%m/%Y"),
|
# group_ids=group["group_id"],
|
||||||
fin=formsemestre.date_fin.strftime("%d/%m/%Y"),
|
# debut=formsemestre.date_debut.strftime("%d/%m/%Y"),
|
||||||
scodoc_dept=g.scodoc_dept,
|
# fin=formsemestre.date_fin.strftime("%d/%m/%Y"),
|
||||||
)
|
# scodoc_dept=g.scodoc_dept,
|
||||||
|
# )
|
||||||
if group["group_name"]:
|
if group["group_name"]:
|
||||||
group["label"] = "groupe %(group_name)s" % group
|
group["label"] = "groupe %(group_name)s" % group
|
||||||
else:
|
else:
|
||||||
|
@ -45,7 +45,7 @@ from app import db
|
|||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_cal
|
||||||
from app.scodoc import sco_excel
|
from app.scodoc import sco_excel
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
@ -829,7 +829,8 @@ def tab_absences_html(groups_infos, etat=None):
|
|||||||
"<li>",
|
"<li>",
|
||||||
form_choix_jour_saisie_hebdo(groups_infos),
|
form_choix_jour_saisie_hebdo(groups_infos),
|
||||||
"</li>",
|
"</li>",
|
||||||
"""<li><a class="stdlink" href="Absences/EtatAbsencesGr?%s&debut=%s&fin=%s">État des absences du groupe</a></li>"""
|
# XXX TODO-ASSIDUITE
|
||||||
|
"""<li><a class="stdlink" href="Absences/EtatAbsencesGr?%s&debut=%s&fin=%s">XXX État des absences du groupe</a></li>"""
|
||||||
% (
|
% (
|
||||||
groups_infos.groups_query_args,
|
groups_infos.groups_query_args,
|
||||||
groups_infos.formsemestre["date_debut"],
|
groups_infos.formsemestre["date_debut"],
|
||||||
@ -890,12 +891,13 @@ def form_choix_jour_saisie_hebdo(groups_infos, moduleimpl_id=None):
|
|||||||
if not authuser.has_permission(Permission.ScoAbsChange):
|
if not authuser.has_permission(Permission.ScoAbsChange):
|
||||||
return ""
|
return ""
|
||||||
sem = groups_infos.formsemestre
|
sem = groups_infos.formsemestre
|
||||||
first_monday = sco_abs.ddmmyyyy(sem["date_debut"]).prev_monday()
|
first_monday = sco_cal.ddmmyyyy(sem["date_debut"]).prev_monday()
|
||||||
today_idx = datetime.date.today().weekday()
|
today_idx = datetime.date.today().weekday()
|
||||||
|
|
||||||
FA = [] # formulaire avec menu saisi absences
|
FA = [] # formulaire avec menu saisi absences
|
||||||
FA.append(
|
FA.append(
|
||||||
'<form id="form_choix_jour_saisie_hebdo" action="Absences/SignaleAbsenceGrSemestre" method="get">'
|
# TODO-ASSIDUITE et utiliser url_for... (was Absences/SignaleAbsenceGrSemestre)
|
||||||
|
'<form id="form_choix_jour_saisie_hebdo" action="XXX" method="get">'
|
||||||
)
|
)
|
||||||
FA.append('<input type="hidden" name="datefin" value="%(date_fin)s"/>' % sem)
|
FA.append('<input type="hidden" name="datefin" value="%(date_fin)s"/>' % sem)
|
||||||
FA.append(groups_infos.get_form_elem())
|
FA.append(groups_infos.get_form_elem())
|
||||||
@ -906,12 +908,12 @@ def form_choix_jour_saisie_hebdo(groups_infos, moduleimpl_id=None):
|
|||||||
FA.append('<input type="hidden" name="destination" value=""/>')
|
FA.append('<input type="hidden" name="destination" value=""/>')
|
||||||
|
|
||||||
FA.append(
|
FA.append(
|
||||||
"""<input type="button" onclick="$('#form_choix_jour_saisie_hebdo')[0].destination.value=get_current_url(); $('#form_choix_jour_saisie_hebdo').submit();" value="Saisir absences du "/>"""
|
"""<input type="button" onclick="$('#form_choix_jour_saisie_hebdo')[0].destination.value=get_current_url(); $('#form_choix_jour_saisie_hebdo').submit();" value="Saisir absences du (NON DISPONIBLE) "/>"""
|
||||||
)
|
)
|
||||||
FA.append("""<select name="datedebut">""")
|
FA.append("""<select name="datedebut">""")
|
||||||
date = first_monday
|
date = first_monday
|
||||||
i = 0
|
i = 0
|
||||||
for jour in sco_abs.day_names():
|
for jour in sco_cal.day_names():
|
||||||
if i == today_idx:
|
if i == today_idx:
|
||||||
sel = "selected"
|
sel = "selected"
|
||||||
else:
|
else:
|
||||||
@ -945,14 +947,17 @@ def form_choix_saisie_semaine(groups_infos):
|
|||||||
) # car ici utilisee dans un format string !
|
) # car ici utilisee dans un format string !
|
||||||
|
|
||||||
DateJour = time.strftime("%d/%m/%Y")
|
DateJour = time.strftime("%d/%m/%Y")
|
||||||
datelundi = sco_abs.ddmmyyyy(DateJour).prev_monday()
|
datelundi = sco_cal.ddmmyyyy(DateJour).prev_monday()
|
||||||
FA = [] # formulaire avec menu saisie hebdo des absences
|
FA = [] # formulaire avec menu saisie hebdo des absences
|
||||||
|
# XXX TODO-ASSIDUITE et utiliser un POST
|
||||||
FA.append('<form action="Absences/SignaleAbsenceGrHebdo" method="get">')
|
FA.append('<form action="Absences/SignaleAbsenceGrHebdo" method="get">')
|
||||||
FA.append('<input type="hidden" name="datelundi" value="%s"/>' % datelundi)
|
FA.append('<input type="hidden" name="datelundi" value="%s"/>' % datelundi)
|
||||||
FA.append('<input type="hidden" name="moduleimpl_id" value="%s"/>' % moduleimpl_id)
|
FA.append('<input type="hidden" name="moduleimpl_id" value="%s"/>' % moduleimpl_id)
|
||||||
FA.append('<input type="hidden" name="destination" value="%s"/>' % destination)
|
FA.append('<input type="hidden" name="destination" value="%s"/>' % destination)
|
||||||
FA.append(groups_infos.get_form_elem())
|
FA.append(groups_infos.get_form_elem())
|
||||||
FA.append('<input type="submit" class="button" value="Saisie à la semaine" />')
|
FA.append(
|
||||||
|
'<input type="submit" class="button" value="Saisie à la semaine (NON DISPONIBLE)" />'
|
||||||
|
) # XXX
|
||||||
FA.append("</form>")
|
FA.append("</form>")
|
||||||
return "\n".join(FA)
|
return "\n".join(FA)
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ def do_moduleimpl_inscription_list(moduleimpl_id=None, etudid=None):
|
|||||||
return _moduleimpl_inscriptionEditor.list(cnx, args)
|
return _moduleimpl_inscriptionEditor.list(cnx, args)
|
||||||
|
|
||||||
|
|
||||||
def moduleimpl_listeetuds(moduleimpl_id):
|
def moduleimpl_listeetuds(moduleimpl_id): # XXX OBSOLETE
|
||||||
"retourne liste des etudids inscrits a ce module"
|
"retourne liste des etudids inscrits a ce module"
|
||||||
req = """SELECT DISTINCT Im.etudid
|
req = """SELECT DISTINCT Im.etudid
|
||||||
FROM notes_moduleimpl_inscription Im,
|
FROM notes_moduleimpl_inscription Im,
|
||||||
|
@ -47,7 +47,7 @@ from app.scodoc.sco_permissions import Permission
|
|||||||
|
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import htmlutils
|
from app.scodoc import htmlutils
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_cal
|
||||||
from app.scodoc import sco_compute_moy
|
from app.scodoc import sco_compute_moy
|
||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
@ -332,10 +332,6 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
'<tr><td colspan="4">'
|
'<tr><td colspan="4">'
|
||||||
# <em title="mode de calcul de la moyenne du module">règle de calcul standard</em>'
|
# <em title="mode de calcul de la moyenne du module">règle de calcul standard</em>'
|
||||||
)
|
)
|
||||||
# if sco_moduleimpl.can_change_ens(moduleimpl_id, raise_exc=False):
|
|
||||||
# H.append(
|
|
||||||
# f' (<a class="stdlink" href="edit_moduleimpl_expr?moduleimpl_id={moduleimpl_id}">changer</a>)'
|
|
||||||
# )
|
|
||||||
H.append("</td></tr>")
|
H.append("</td></tr>")
|
||||||
H.append(
|
H.append(
|
||||||
f"""<tr><td colspan="4"><span class="moduleimpl_abs_link"><a class="stdlink"
|
f"""<tr><td colspan="4"><span class="moduleimpl_abs_link"><a class="stdlink"
|
||||||
@ -349,17 +345,20 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
current_user.has_permission(Permission.ScoAbsChange)
|
current_user.has_permission(Permission.ScoAbsChange)
|
||||||
and formsemestre.est_courant()
|
and formsemestre.est_courant()
|
||||||
):
|
):
|
||||||
datelundi = sco_abs.ddmmyyyy(time.strftime("%d/%m/%Y")).prev_monday()
|
datelundi = sco_cal.ddmmyyyy(time.strftime("%d/%m/%Y")).prev_monday()
|
||||||
group_id = sco_groups.get_default_group(formsemestre_id)
|
group_id = sco_groups.get_default_group(formsemestre_id)
|
||||||
H.append(
|
H.append(
|
||||||
f"""
|
f"""
|
||||||
<span class="moduleimpl_abs_link"><a class="stdlink"
|
<span class="moduleimpl_abs_link"><a class="stdlink" href="XXX"
|
||||||
href="{url_for("absences.SignaleAbsenceGrHebdo",
|
>Saisie Absences hebdo. (INDISPONIBLE)</a></span>
|
||||||
scodoc_dept=g.scodoc_dept,formsemestre_id=formsemestre_id,
|
|
||||||
moduleimpl_id=moduleimpl_id, datelundi=datelundi, group_ids=group_id)}">
|
|
||||||
Saisie Absences hebdo.</a></span>
|
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
# TODO-ASSIDUITE
|
||||||
|
# href="{
|
||||||
|
# url_for("absences.SignaleAbsenceGrHebdo",
|
||||||
|
# scodoc_dept=g.scodoc_dept,formsemestre_id=formsemestre_id,
|
||||||
|
# moduleimpl_id=moduleimpl_id, datelundi=datelundi, group_ids=group_id)
|
||||||
|
# }"
|
||||||
|
|
||||||
H.append("</td></tr></table>")
|
H.append("</td></tr></table>")
|
||||||
#
|
#
|
||||||
|
@ -45,7 +45,6 @@ from app.models import (
|
|||||||
FormSemestre,
|
FormSemestre,
|
||||||
Module,
|
Module,
|
||||||
ModuleImpl,
|
ModuleImpl,
|
||||||
NotesNotes,
|
|
||||||
ScolarNews,
|
ScolarNews,
|
||||||
)
|
)
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
@ -54,16 +53,13 @@ from app.scodoc.sco_exceptions import (
|
|||||||
AccessDenied,
|
AccessDenied,
|
||||||
InvalidNoteValue,
|
InvalidNoteValue,
|
||||||
NoteProcessError,
|
NoteProcessError,
|
||||||
ScoBugCatcher,
|
|
||||||
ScoException,
|
ScoException,
|
||||||
ScoInvalidParamError,
|
ScoInvalidParamError,
|
||||||
ScoValueError,
|
ScoValueError,
|
||||||
)
|
)
|
||||||
from app.scodoc import html_sco_header, sco_users
|
from app.scodoc import html_sco_header, sco_users
|
||||||
from app.scodoc import htmlutils
|
from app.scodoc import htmlutils
|
||||||
from app.scodoc import sco_abs
|
|
||||||
from app.scodoc import sco_cache
|
from app.scodoc import sco_cache
|
||||||
from app.scodoc import sco_edit_module
|
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
@ -71,7 +67,6 @@ from app.scodoc import sco_excel
|
|||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_groups_view
|
from app.scodoc import sco_groups_view
|
||||||
from app.scodoc import sco_moduleimpl
|
|
||||||
from app.scodoc import sco_permissions_check
|
from app.scodoc import sco_permissions_check
|
||||||
from app.scodoc import sco_undo_notes
|
from app.scodoc import sco_undo_notes
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
@ -1113,16 +1108,16 @@ def _get_sorted_etuds(evaluation: Evaluation, etudids: list, formsemestre_id: in
|
|||||||
)
|
)
|
||||||
warn_abs_lst = []
|
warn_abs_lst = []
|
||||||
if evaluation.is_matin():
|
if evaluation.is_matin():
|
||||||
nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=True)
|
nbabs = 0 # TODO-ASSIDUITE sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=True)
|
||||||
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=True)
|
nbabsjust = 0 # TODO-ASSIDUITE sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=True)
|
||||||
if nbabs:
|
if nbabs:
|
||||||
if nbabsjust:
|
if nbabsjust:
|
||||||
warn_abs_lst.append("absent justifié le matin !")
|
warn_abs_lst.append("absent justifié le matin !")
|
||||||
else:
|
else:
|
||||||
warn_abs_lst.append("absent le matin !")
|
warn_abs_lst.append("absent le matin !")
|
||||||
if evaluation.is_apresmidi():
|
if evaluation.is_apresmidi():
|
||||||
nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=0)
|
nbabs = 0 # TODO-ASSIDUITE sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=0)
|
||||||
nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0)
|
nbabsjust = 0 # TODO-ASSIDUITE sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0)
|
||||||
if nbabs:
|
if nbabs:
|
||||||
if nbabsjust:
|
if nbabsjust:
|
||||||
warn_abs_lst.append("absent justifié l'après-midi !")
|
warn_abs_lst.append("absent justifié l'après-midi !")
|
||||||
|
@ -41,7 +41,7 @@ from reportlab.lib.units import cm
|
|||||||
from reportlab.platypus import KeepInFrame, Paragraph, Table, TableStyle
|
from reportlab.platypus import KeepInFrame, Paragraph, Table, TableStyle
|
||||||
from reportlab.platypus.doctemplate import BaseDocTemplate
|
from reportlab.platypus.doctemplate import BaseDocTemplate
|
||||||
|
|
||||||
from app.scodoc import sco_abs
|
from app.scodoc import sco_cal
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc.sco_exceptions import ScoPDFFormatError
|
from app.scodoc.sco_exceptions import ScoPDFFormatError
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
@ -299,9 +299,9 @@ def pdf_feuille_releve_absences(
|
|||||||
NB_CELL_PM = sco_preferences.get_preference("feuille_releve_abs_PM")
|
NB_CELL_PM = sco_preferences.get_preference("feuille_releve_abs_PM")
|
||||||
col_width = 0.85 * cm
|
col_width = 0.85 * cm
|
||||||
if sco_preferences.get_preference("feuille_releve_abs_samedi"):
|
if sco_preferences.get_preference("feuille_releve_abs_samedi"):
|
||||||
days = sco_abs.DAYNAMES[:6] # Lundi, ..., Samedi
|
days = sco_cal.DAYNAMES[:6] # Lundi, ..., Samedi
|
||||||
else:
|
else:
|
||||||
days = sco_abs.DAYNAMES[:5] # Lundi, ..., Vendredi
|
days = sco_cal.DAYNAMES[:5] # Lundi, ..., Vendredi
|
||||||
nb_days = len(days)
|
nb_days = len(days)
|
||||||
|
|
||||||
# Informations sur les groupes à afficher:
|
# Informations sur les groupes à afficher:
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
// JS Ajax code for SignaleAbsenceGrSemestre
|
|
||||||
// Contributed by YLB
|
|
||||||
|
|
||||||
function ajaxFunction(mod, etudid, dat) {
|
|
||||||
var ajaxRequest; // The variable that makes Ajax possible!
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Opera 8.0+, Firefox, Safari
|
|
||||||
ajaxRequest = new XMLHttpRequest();
|
|
||||||
} catch (e) {
|
|
||||||
// Internet Explorer Browsers
|
|
||||||
try {
|
|
||||||
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
|
|
||||||
} catch (e) {
|
|
||||||
try {
|
|
||||||
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
|
|
||||||
} catch (e) {
|
|
||||||
// Something went wrong
|
|
||||||
alert("Your browser broke!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Create a function that will receive data sent from the server
|
|
||||||
ajaxRequest.onreadystatechange = function () {
|
|
||||||
if (ajaxRequest.readyState == 4 && ajaxRequest.status == 200) {
|
|
||||||
document.getElementById("AjaxDiv").innerHTML = ajaxRequest.responseText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ajaxRequest.open("POST", SCO_URL + "/Absences/doSignaleAbsenceGrSemestre", true);
|
|
||||||
ajaxRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
|
||||||
var oSelectOne = $("#abs_form")[0].elements["moduleimpl_id"];
|
|
||||||
var index = oSelectOne.selectedIndex;
|
|
||||||
var modul_id = oSelectOne.options[index].value;
|
|
||||||
if (mod == 'add') {
|
|
||||||
ajaxRequest.send("reply=0&moduleimpl_id=" + modul_id + "&abslist:list=" + etudid + ":" + dat);
|
|
||||||
}
|
|
||||||
if (mod == 'remove') {
|
|
||||||
ajaxRequest.send("reply=0&moduleimpl_id=" + modul_id + "&etudids=" + etudid + "&dates=" + dat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----
|
|
||||||
function change_moduleimpl(url) {
|
|
||||||
document.location = url + '&moduleimpl_id=' + document.getElementById('moduleimpl_id').value;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -547,7 +547,6 @@ def signal_assiduites_group():
|
|||||||
+ [
|
+ [
|
||||||
# Voir fonctionnement JS
|
# Voir fonctionnement JS
|
||||||
"js/etud_info.js",
|
"js/etud_info.js",
|
||||||
"js/abs_ajax.js",
|
|
||||||
"js/groups_view.js",
|
"js/groups_view.js",
|
||||||
"js/assiduites.js",
|
"js/assiduites.js",
|
||||||
"libjs/moment.new.min.js",
|
"libjs/moment.new.min.js",
|
||||||
|
@ -97,9 +97,9 @@ from app.scodoc.sco_exceptions import (
|
|||||||
)
|
)
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.pe import pe_view
|
from app.pe import pe_view
|
||||||
from app.scodoc import sco_abs
|
|
||||||
from app.scodoc import sco_apogee_compare
|
from app.scodoc import sco_apogee_compare
|
||||||
from app.scodoc import sco_archives
|
from app.scodoc import sco_archives
|
||||||
|
from app.scodoc import sco_assiduites
|
||||||
from app.scodoc import sco_bulletins
|
from app.scodoc import sco_bulletins
|
||||||
from app.scodoc import sco_bulletins_pdf
|
from app.scodoc import sco_bulletins_pdf
|
||||||
from app.scodoc import sco_cache
|
from app.scodoc import sco_cache
|
||||||
@ -1152,175 +1152,64 @@ def edit_moduleimpl_resp(moduleimpl_id: int):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
_EXPR_HELP = """<p class="help">Expérimental: formule de calcul de la moyenne %(target)s</p>
|
|
||||||
<p class="help">Attention: l'utilisation de formules ralentit considérablement
|
|
||||||
les traitements. A utiliser uniquement dans les cas ne pouvant pas être traités autrement.</p>
|
|
||||||
<p class="help">Dans la formule, les variables suivantes sont définies:</p>
|
|
||||||
<ul class="help">
|
|
||||||
<li><tt>moy</tt> la moyenne, calculée selon la règle standard (moyenne pondérée)</li>
|
|
||||||
<li><tt>moy_is_valid</tt> vrai si la moyenne est valide (numérique)</li>
|
|
||||||
<li><tt>moy_val</tt> la valeur de la moyenne (nombre, valant 0 si invalide)</li>
|
|
||||||
<li><tt>notes</tt> vecteur des notes (/20) aux %(objs)s</li>
|
|
||||||
<li><tt>coefs</tt> vecteur des coefficients des %(objs)s, les coefs des %(objs)s sans notes (ATT, EXC) étant mis à zéro</li>
|
|
||||||
<li><tt>cmask</tt> vecteur de 0/1, 0 si le coef correspondant a été annulé</li>
|
|
||||||
<li>Nombre d'absences: <tt>nb_abs</tt>, <tt>nb_abs_just</tt>, <tt>nb_abs_nojust</tt> (en demi-journées)</li>
|
|
||||||
</ul>
|
|
||||||
<p class="help">Les éléments des vecteurs sont ordonnés dans l'ordre des %(objs)s%(ordre)s.</p>
|
|
||||||
<p class="help">Les fonctions suivantes sont utilisables: <tt>abs, cmp, dot, len, map, max, min, pow, reduce, round, sum, ifelse</tt>.</p>
|
|
||||||
<p class="help">La notation <tt>V(1,2,3)</tt> représente un vecteur <tt>(1,2,3)</tt>.</p>
|
|
||||||
<p class="help"></p>Pour indiquer que la note calculée n'existe pas, utiliser la chaîne <tt>'NA'</tt>.</p>
|
|
||||||
<p class="help">Vous pouvez désactiver la formule (et revenir au mode de calcul "classique")
|
|
||||||
en supprimant le texte ou en faisant précéder la première ligne par <tt>#</tt></p>
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/edit_moduleimpl_expr", methods=["GET", "POST"])
|
|
||||||
@scodoc
|
|
||||||
@permission_required(Permission.ScoView)
|
|
||||||
@scodoc7func
|
|
||||||
def edit_moduleimpl_expr(moduleimpl_id):
|
|
||||||
"""Edition formule calcul moyenne module
|
|
||||||
Accessible par Admin, dir des etud et responsable module
|
|
||||||
|
|
||||||
Inutilisé en ScoDoc 9.
|
|
||||||
"""
|
|
||||||
M, sem = sco_moduleimpl.can_change_ens(moduleimpl_id)
|
|
||||||
H = [
|
|
||||||
html_sco_header.html_sem_header(
|
|
||||||
'Modification règle de calcul du <a href="moduleimpl_status?moduleimpl_id=%s">module %s</a>'
|
|
||||||
% (moduleimpl_id, M["module"]["titre"]),
|
|
||||||
),
|
|
||||||
_EXPR_HELP
|
|
||||||
% {
|
|
||||||
"target": "du module",
|
|
||||||
"objs": "évaluations",
|
|
||||||
"ordre": " (le premier élément est la plus ancienne évaluation)",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
initvalues = M
|
|
||||||
form = [
|
|
||||||
("moduleimpl_id", {"input_type": "hidden"}),
|
|
||||||
(
|
|
||||||
"computation_expr",
|
|
||||||
{
|
|
||||||
"title": "Formule de calcul",
|
|
||||||
"input_type": "textarea",
|
|
||||||
"rows": 4,
|
|
||||||
"cols": 60,
|
|
||||||
"explanation": "formule de calcul (expérimental)",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
tf = TrivialFormulator(
|
|
||||||
request.base_url,
|
|
||||||
scu.get_request_args(),
|
|
||||||
form,
|
|
||||||
submitlabel="Modifier formule de calcul",
|
|
||||||
cancelbutton="Annuler",
|
|
||||||
initvalues=initvalues,
|
|
||||||
)
|
|
||||||
if tf[0] == 0:
|
|
||||||
return "\n".join(H) + tf[1] + html_sco_header.sco_footer()
|
|
||||||
elif tf[0] == -1:
|
|
||||||
return flask.redirect(
|
|
||||||
url_for(
|
|
||||||
"notes.moduleimpl_status",
|
|
||||||
scodoc_dept=g.scodoc_dept,
|
|
||||||
moduleimpl_id=moduleimpl_id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
sco_moduleimpl.do_moduleimpl_edit(
|
|
||||||
{
|
|
||||||
"moduleimpl_id": moduleimpl_id,
|
|
||||||
"computation_expr": tf[2]["computation_expr"],
|
|
||||||
},
|
|
||||||
formsemestre_id=sem["formsemestre_id"],
|
|
||||||
)
|
|
||||||
sco_cache.invalidate_formsemestre(
|
|
||||||
formsemestre_id=sem["formsemestre_id"]
|
|
||||||
) # > modif regle calcul
|
|
||||||
flash("règle de calcul modifiée")
|
|
||||||
return flask.redirect(
|
|
||||||
url_for(
|
|
||||||
"notes.moduleimpl_status",
|
|
||||||
scodoc_dept=g.scodoc_dept,
|
|
||||||
moduleimpl_id=moduleimpl_id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/delete_moduleimpl_expr", methods=["GET", "POST"])
|
|
||||||
@scodoc
|
|
||||||
@permission_required(Permission.ScoView)
|
|
||||||
@scodoc7func
|
|
||||||
def delete_moduleimpl_expr(moduleimpl_id):
|
|
||||||
"""Suppression formule calcul moyenne module
|
|
||||||
Accessible par Admin, dir des etud et responsable module
|
|
||||||
"""
|
|
||||||
modimpl = ModuleImpl.query.get_or_404(moduleimpl_id)
|
|
||||||
sco_moduleimpl.can_change_ens(moduleimpl_id)
|
|
||||||
modimpl.computation_expr = None
|
|
||||||
db.session.add(modimpl)
|
|
||||||
db.session.commit()
|
|
||||||
flash("Ancienne formule supprimée")
|
|
||||||
return flask.redirect(
|
|
||||||
url_for(
|
|
||||||
"notes.moduleimpl_status",
|
|
||||||
scodoc_dept=g.scodoc_dept,
|
|
||||||
moduleimpl_id=moduleimpl_id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/view_module_abs")
|
@bp.route("/view_module_abs")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
def view_module_abs(moduleimpl_id, format="html"):
|
def view_module_abs(moduleimpl_id, fmt="html"):
|
||||||
"""Visualisation des absences a un module"""
|
"""Visualisation des absences a un module"""
|
||||||
M = sco_moduleimpl.moduleimpl_withmodule_list(moduleimpl_id=moduleimpl_id)[0]
|
modimpl: ModuleImpl = (
|
||||||
sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"])
|
ModuleImpl.query.filter_by(id=moduleimpl_id)
|
||||||
debut_sem = ndb.DateDMYtoISO(sem["date_debut"])
|
.join(FormSemestre)
|
||||||
fin_sem = ndb.DateDMYtoISO(sem["date_fin"])
|
.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
list_insc = sco_moduleimpl.moduleimpl_listeetuds(moduleimpl_id)
|
).first_or_404()
|
||||||
|
|
||||||
T = []
|
debut_sem = modimpl.formsemestre.date_debut
|
||||||
for etudid in list_insc:
|
fin_sem = modimpl.formsemestre.date_fin
|
||||||
nb_abs = sco_abs.count_abs(
|
inscrits: list[Identite] = sorted(
|
||||||
etudid=etudid,
|
[i.etud for i in modimpl.inscriptions], key=lambda e: e.sort_key
|
||||||
debut=debut_sem,
|
)
|
||||||
fin=fin_sem,
|
|
||||||
moduleimpl_id=moduleimpl_id,
|
rows = []
|
||||||
|
for etud in inscrits:
|
||||||
|
# TODO-ASSIDUITE ne va pas car ne filtre pas sur le moduleimpl
|
||||||
|
# nb_abs, nb_abs_just = sco_assiduites.formsemestre_get_assiduites_count(etud.id, modimpl.formsemestre)
|
||||||
|
nb_abs, nb_abs_just = 0, 0 # XXX TODO-ASSIDUITE
|
||||||
|
# nb_abs = sco_abs.count_abs(
|
||||||
|
# etudid=etud.id,
|
||||||
|
# debut=debut_sem,
|
||||||
|
# fin=fin_sem,
|
||||||
|
# moduleimpl_id=moduleimpl_id,
|
||||||
|
# )
|
||||||
|
# if nb_abs:
|
||||||
|
# nb_abs_just = sco_abs.count_abs_just(
|
||||||
|
# etudid=etud.id,
|
||||||
|
# debut=debut_sem,
|
||||||
|
# fin=fin_sem,
|
||||||
|
# moduleimpl_id=moduleimpl_id,
|
||||||
|
# )
|
||||||
|
rows.append(
|
||||||
|
{
|
||||||
|
"nomprenom": etud.nomprenom,
|
||||||
|
"just": nb_abs_just,
|
||||||
|
"nojust": nb_abs - nb_abs_just,
|
||||||
|
"total": nb_abs,
|
||||||
|
"_nomprenom_target": url_for(
|
||||||
|
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etud.id
|
||||||
|
),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
if nb_abs:
|
|
||||||
nb_abs_just = sco_abs.count_abs_just(
|
|
||||||
etudid=etudid,
|
|
||||||
debut=debut_sem,
|
|
||||||
fin=fin_sem,
|
|
||||||
moduleimpl_id=moduleimpl_id,
|
|
||||||
)
|
|
||||||
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
|
|
||||||
T.append(
|
|
||||||
{
|
|
||||||
"nomprenom": etud["nomprenom"],
|
|
||||||
"just": nb_abs_just,
|
|
||||||
"nojust": nb_abs - nb_abs_just,
|
|
||||||
"total": nb_abs,
|
|
||||||
"_nomprenom_target": url_for(
|
|
||||||
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.html_sem_header(
|
html_sco_header.html_sem_header(
|
||||||
'Absences du <a href="moduleimpl_status?moduleimpl_id=%s">module %s</a>'
|
f"""Absences du <a href="{
|
||||||
% (moduleimpl_id, M["module"]["titre"]),
|
url_for("notes.moduleimpl_status",
|
||||||
page_title="Absences du module %s" % (M["module"]["titre"]),
|
scodoc_dept=g.scodoc_dept, moduleimpl_id=moduleimpl_id
|
||||||
|
)}">module {modimpl.module.titre_str()}</a>""",
|
||||||
|
page_title=f"Absences du module {modimpl.module.titre_str()}",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
if not T and format == "html":
|
if not rows and fmt == "html":
|
||||||
return (
|
return (
|
||||||
"\n".join(H)
|
"\n".join(H)
|
||||||
+ "<p>Aucune absence signalée</p>"
|
+ "<p>Aucune absence signalée</p>"
|
||||||
@ -1335,16 +1224,16 @@ def view_module_abs(moduleimpl_id, format="html"):
|
|||||||
"total": "Total",
|
"total": "Total",
|
||||||
},
|
},
|
||||||
columns_ids=("nomprenom", "just", "nojust", "total"),
|
columns_ids=("nomprenom", "just", "nojust", "total"),
|
||||||
rows=T,
|
rows=rows,
|
||||||
html_class="table_leftalign",
|
html_class="table_leftalign",
|
||||||
base_url="%s?moduleimpl_id=%s" % (request.base_url, moduleimpl_id),
|
base_url=f"{request.base_url}?moduleimpl_id={moduleimpl_id}",
|
||||||
filename="absmodule_" + scu.make_filename(M["module"]["titre"]),
|
filename="absmodule_" + scu.make_filename(modimpl.module.titre_str()),
|
||||||
caption="Absences dans le module %s" % M["module"]["titre"],
|
caption=f"Absences dans le module {modimpl.module.titre_str()}",
|
||||||
preferences=sco_preferences.SemPreferences(),
|
preferences=sco_preferences.SemPreferences(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if format != "html":
|
if fmt != "html":
|
||||||
return tab.make_page(format=format)
|
return tab.make_page(format=fmt)
|
||||||
|
|
||||||
return "\n".join(H) + tab.html() + html_sco_header.sco_footer()
|
return "\n".join(H) + tab.html() + html_sco_header.sco_footer()
|
||||||
|
|
||||||
|
@ -1,117 +0,0 @@
|
|||||||
# -*- mode: python -*-
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
Comptage des absences
|
|
||||||
"""
|
|
||||||
# test écrit par Fares Amer, mai 2021 et porté sur ScoDoc 8 en juillet 2021
|
|
||||||
|
|
||||||
from tests.unit import sco_fake_gen
|
|
||||||
|
|
||||||
from app.scodoc import sco_abs, sco_formsemestre
|
|
||||||
from app.scodoc import sco_abs_views
|
|
||||||
|
|
||||||
|
|
||||||
def test_abs_counts(test_client):
|
|
||||||
"""Comptage des absences"""
|
|
||||||
G = sco_fake_gen.ScoFake(verbose=False)
|
|
||||||
|
|
||||||
# --- Création d'étudiants
|
|
||||||
etud = G.create_etud(code_nip=None)
|
|
||||||
|
|
||||||
# --- Création d'une formation
|
|
||||||
formation_id = G.create_formation(acronyme="")
|
|
||||||
ue_id = G.create_ue(formation_id=formation_id, acronyme="TST1", titre="ue test")
|
|
||||||
matiere_id = G.create_matiere(ue_id=ue_id, titre="matière test")
|
|
||||||
module_id = G.create_module(
|
|
||||||
matiere_id=matiere_id,
|
|
||||||
code="TSM1",
|
|
||||||
coefficient=1.0,
|
|
||||||
titre="module test",
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Mise place d'un semestre
|
|
||||||
formsemestre_id = G.create_formsemestre(
|
|
||||||
formation_id=formation_id,
|
|
||||||
semestre_id=1,
|
|
||||||
date_debut="01/01/2021",
|
|
||||||
date_fin="30/06/2021",
|
|
||||||
)
|
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
|
||||||
_ = G.create_moduleimpl(
|
|
||||||
module_id=module_id,
|
|
||||||
formsemestre_id=formsemestre_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Inscription des étudiants
|
|
||||||
G.inscrit_etudiant(formsemestre_id, etud)
|
|
||||||
|
|
||||||
# --- Saisie absences
|
|
||||||
etudid = etud["etudid"]
|
|
||||||
|
|
||||||
for debut, fin, demijournee in [
|
|
||||||
("01/01/2020", "31/01/2020", 2), # hors semestre
|
|
||||||
("15/01/2021", "15/01/2021", 1),
|
|
||||||
("18/01/2021", "18/01/2021", 0),
|
|
||||||
("19/01/2021", "19/01/2021", 2),
|
|
||||||
("22/01/2021", "22/01/2021", 1),
|
|
||||||
("30/06/2021", "30/06/2021", 2), # dernier jour
|
|
||||||
]:
|
|
||||||
sco_abs_views.doSignaleAbsence(
|
|
||||||
datedebut=debut,
|
|
||||||
datefin=fin,
|
|
||||||
demijournee=demijournee,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Justification de certaines absences
|
|
||||||
|
|
||||||
for debut, fin, demijournee in [
|
|
||||||
("15/01/2021", "15/01/2021", 1),
|
|
||||||
("18/01/2021", "18/01/2021", 0),
|
|
||||||
("19/01/2021", "19/01/2021", 2),
|
|
||||||
]:
|
|
||||||
sco_abs_views.doJustifAbsence(
|
|
||||||
datedebut=debut,
|
|
||||||
datefin=fin,
|
|
||||||
demijournee=demijournee,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Utilisation de get_abs_count() de sco_abs
|
|
||||||
|
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
|
||||||
|
|
||||||
# --- Utilisation de sco_abs.count_abs()
|
|
||||||
|
|
||||||
nb_abs2 = sco_abs.count_abs(etudid=etudid, debut="2021-01-01", fin="2021-06-30")
|
|
||||||
nb_absj2 = sco_abs.count_abs_just(
|
|
||||||
etudid=etudid, debut="2021-01-01", fin="2021-06-30"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert nbabs == nb_abs2 == 7
|
|
||||||
assert nbabsjust == nb_absj2 == 4
|
|
||||||
|
|
||||||
# --- Nombre de justificatifs:
|
|
||||||
justifs = sco_abs.list_abs_justifs(etudid, "2021-01-01", datefin="2021-06-30")
|
|
||||||
assert len(justifs) == 4
|
|
||||||
|
|
||||||
# --- Suppression d'absence
|
|
||||||
_ = sco_abs_views.doAnnuleAbsence("19/01/2021", "19/01/2021", 2, etudid=etudid)
|
|
||||||
|
|
||||||
# --- Vérification
|
|
||||||
justifs_2 = sco_abs.list_abs_justifs(etudid, "2021-01-01", datefin="2021-06-30")
|
|
||||||
assert len(justifs_2) == len(justifs)
|
|
||||||
new_nbabs, _ = sco_abs.get_abs_count(etudid, sem) # version cachée
|
|
||||||
new_nbabs2 = sco_abs.count_abs(etudid=etudid, debut="2021-01-01", fin="2021-06-30")
|
|
||||||
|
|
||||||
assert new_nbabs == new_nbabs2
|
|
||||||
assert new_nbabs == (nbabs - 2) # on a supprimé deux absences
|
|
||||||
|
|
||||||
# --- annulation absence sans supprimer le justificatif
|
|
||||||
sco_abs_views.AnnuleAbsencesDatesNoJust(etudid, ["2021-01-15"])
|
|
||||||
nbabs_3, nbjust_3 = sco_abs.get_abs_count(etudid, sem)
|
|
||||||
assert nbabs_3 == new_nbabs
|
|
||||||
justifs_3 = sco_abs.list_abs_justifs(etudid, "2021-01-01", datefin="2021-06-30")
|
|
||||||
assert len(justifs_3) == len(justifs_2)
|
|
||||||
# XXX à continuer
|
|
@ -1,344 +0,0 @@
|
|||||||
# -*- mode: python -*-
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
Créer et justifier des absences en utilisant le parametre demijournee
|
|
||||||
"""
|
|
||||||
# test écrit par Fares Amer, mai 2021 et porté sur ScoDoc 8 en juillet 2021
|
|
||||||
import datetime
|
|
||||||
import json
|
|
||||||
|
|
||||||
from tests.unit import sco_fake_gen
|
|
||||||
from app import db
|
|
||||||
from app.models import Module
|
|
||||||
from app.scodoc import sco_abs
|
|
||||||
from app.scodoc import sco_abs_views
|
|
||||||
from app.scodoc import sco_groups
|
|
||||||
from app.scodoc import sco_formsemestre
|
|
||||||
from app.scodoc import sco_preferences
|
|
||||||
from app.views import absences
|
|
||||||
|
|
||||||
|
|
||||||
def test_abs_demijournee(test_client):
|
|
||||||
"""Opération élémentaires sur les absences, tests demi-journées
|
|
||||||
Travaille dans base TEST00 (defaut)
|
|
||||||
"""
|
|
||||||
G = sco_fake_gen.ScoFake(verbose=False)
|
|
||||||
|
|
||||||
# --- Création d'étudiants
|
|
||||||
etud = G.create_etud(code_nip=None)
|
|
||||||
|
|
||||||
# --- Création d'une formation
|
|
||||||
formation_id = G.create_formation(acronyme="")
|
|
||||||
ue_id = G.create_ue(formation_id=formation_id, acronyme="TST1", titre="ue test")
|
|
||||||
matiere_id = G.create_matiere(ue_id=ue_id, titre="matière test")
|
|
||||||
module_id = G.create_module(
|
|
||||||
matiere_id=matiere_id,
|
|
||||||
code="TSM1",
|
|
||||||
coefficient=1.0,
|
|
||||||
titre="module test",
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Mise place d'un semestre
|
|
||||||
formsemestre_id = G.create_formsemestre(
|
|
||||||
formation_id=formation_id,
|
|
||||||
semestre_id=1,
|
|
||||||
date_debut="01/01/2021",
|
|
||||||
date_fin="30/06/2021",
|
|
||||||
)
|
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
|
||||||
|
|
||||||
_ = G.create_moduleimpl(
|
|
||||||
module_id=module_id,
|
|
||||||
formsemestre_id=formsemestre_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Inscription des étudiants
|
|
||||||
G.inscrit_etudiant(formsemestre_id, etud)
|
|
||||||
|
|
||||||
# --- Saisie absences
|
|
||||||
etudid = etud["etudid"]
|
|
||||||
|
|
||||||
_ = sco_abs_views.doSignaleAbsence(
|
|
||||||
"15/01/2021",
|
|
||||||
"15/01/2021",
|
|
||||||
demijournee=2,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = sco_abs_views.doSignaleAbsence(
|
|
||||||
"18/01/2021",
|
|
||||||
"18/01/2021",
|
|
||||||
demijournee=1,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = sco_abs_views.doSignaleAbsence(
|
|
||||||
"19/01/2021",
|
|
||||||
"19/01/2021",
|
|
||||||
demijournee=0,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Justification de certaines absences
|
|
||||||
|
|
||||||
_ = sco_abs_views.doJustifAbsence(
|
|
||||||
"18/01/2021",
|
|
||||||
"18/01/2021",
|
|
||||||
demijournee=1,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = sco_abs_views.doJustifAbsence(
|
|
||||||
"19/01/2021",
|
|
||||||
"19/01/2021",
|
|
||||||
demijournee=2,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
# NE JUSTIFIE QUE LE MATIN MALGRES LE PARAMETRE demijournee = 2
|
|
||||||
|
|
||||||
# --- Test
|
|
||||||
|
|
||||||
nbabs, nbabs_just = sco_abs.get_abs_count(etudid, sem)
|
|
||||||
assert (
|
|
||||||
nbabs == 4
|
|
||||||
) # l'étudiant a été absent le 15 journée compléte (2 abs : 1 matin, 1 apres midi) et le 18 (1 matin), et le 19 (1 apres midi).
|
|
||||||
assert nbabs_just == 2 # Justifie abs du matin + abs après midi
|
|
||||||
|
|
||||||
|
|
||||||
def test_abs_basic(test_client):
|
|
||||||
"""creation de 10 étudiants, formation, semestre, ue, module, absences le matin, l'apres midi, la journée compléte
|
|
||||||
et justification d'absences, supression d'absences, création d'une liste etat absences, creation d'un groupe afin
|
|
||||||
de tester la fonction EtatAbsencesGroupes
|
|
||||||
|
|
||||||
Fonctions de l'API utilisé :
|
|
||||||
- doSignaleAbsence
|
|
||||||
- doAnnuleAbsence
|
|
||||||
- doJustifAbsence
|
|
||||||
- get_partition_groups
|
|
||||||
- get_partitions_list
|
|
||||||
- sco_abs.get_abs_count(etudid, sem)
|
|
||||||
- ListeAbsEtud
|
|
||||||
- partition_create
|
|
||||||
- create_group
|
|
||||||
- set_group
|
|
||||||
- EtatAbsencesGr
|
|
||||||
- AddBilletAbsence
|
|
||||||
- billets_etud
|
|
||||||
"""
|
|
||||||
G = sco_fake_gen.ScoFake(verbose=False)
|
|
||||||
|
|
||||||
# --- Création d'étudiants
|
|
||||||
etuds = [G.create_etud(code_nip=None) for _ in range(10)]
|
|
||||||
|
|
||||||
# --- Création d'une formation
|
|
||||||
formation_id = G.create_formation(acronyme="")
|
|
||||||
ue_id = G.create_ue(formation_id=formation_id, acronyme="TST1", titre="ue test")
|
|
||||||
matiere_id = G.create_matiere(ue_id=ue_id, titre="matière test")
|
|
||||||
module_id = G.create_module(
|
|
||||||
matiere_id=matiere_id,
|
|
||||||
code="TSM1",
|
|
||||||
coefficient=1.0,
|
|
||||||
titre="module test",
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Mise place d'un semestre
|
|
||||||
formsemestre_id = G.create_formsemestre(
|
|
||||||
formation_id=formation_id,
|
|
||||||
semestre_id=1,
|
|
||||||
date_debut="01/01/2021",
|
|
||||||
date_fin="30/06/2021",
|
|
||||||
)
|
|
||||||
|
|
||||||
moduleimpl_id = G.create_moduleimpl(
|
|
||||||
module_id=module_id,
|
|
||||||
formsemestre_id=formsemestre_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Inscription des étudiants
|
|
||||||
for etud in etuds:
|
|
||||||
G.inscrit_etudiant(formsemestre_id, etud)
|
|
||||||
|
|
||||||
# --- Création d'une évaluation
|
|
||||||
e = G.create_evaluation(
|
|
||||||
moduleimpl_id=moduleimpl_id,
|
|
||||||
date_debut=datetime.datetime(2021, 1, 22),
|
|
||||||
description="evaluation test",
|
|
||||||
coefficient=1.0,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Saisie absences
|
|
||||||
etudid = etuds[0]["etudid"]
|
|
||||||
|
|
||||||
_ = sco_abs_views.doSignaleAbsence(
|
|
||||||
"15/01/2021",
|
|
||||||
"15/01/2021",
|
|
||||||
demijournee=1,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = sco_abs_views.doSignaleAbsence(
|
|
||||||
"18/01/2021",
|
|
||||||
"18/01/2021",
|
|
||||||
demijournee=0,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = sco_abs_views.doSignaleAbsence(
|
|
||||||
"19/01/2021",
|
|
||||||
"19/01/2021",
|
|
||||||
demijournee=2,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = sco_abs_views.doSignaleAbsence(
|
|
||||||
"22/01/2021",
|
|
||||||
"22/01/2021",
|
|
||||||
demijournee=1,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Justification de certaines absences
|
|
||||||
|
|
||||||
_ = sco_abs_views.doJustifAbsence(
|
|
||||||
"15/01/2021",
|
|
||||||
"15/01/2021",
|
|
||||||
demijournee=1,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = sco_abs_views.doJustifAbsence(
|
|
||||||
"18/01/2021",
|
|
||||||
"18/01/2021",
|
|
||||||
demijournee=0,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = sco_abs_views.doJustifAbsence(
|
|
||||||
"19/01/2021",
|
|
||||||
"19/01/2021",
|
|
||||||
demijournee=2,
|
|
||||||
etudid=etudid,
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Test
|
|
||||||
|
|
||||||
b = sco_abs.is_work_saturday()
|
|
||||||
assert b == 0 # samedi ne sont pas compris
|
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
|
||||||
# l'étudiant a été absent le 15 (apres midi) , (16 et 17 we),
|
|
||||||
# 18 (matin) et 19 janvier (matin et apres midi), et 22 (matin)
|
|
||||||
assert nbabs == 5
|
|
||||||
# l'étudiant justifie ses abs du 15, 18 et 19
|
|
||||||
assert nbabsjust == 4
|
|
||||||
|
|
||||||
# --- Suppression d'une absence et d'une justification
|
|
||||||
|
|
||||||
_ = sco_abs_views.doAnnuleAbsence("19/01/2021", "19/01/2021", 2, etudid=etudid)
|
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
|
||||||
assert nbabs == 3
|
|
||||||
assert nbabsjust == 2
|
|
||||||
|
|
||||||
# --- suppression d'une justification pas encore disponible à l'aide de python.
|
|
||||||
|
|
||||||
# --- Création d'une liste d'abs
|
|
||||||
|
|
||||||
liste_abs = sco_abs_views.ListeAbsEtud(
|
|
||||||
etudid, format="json", absjust_only=1, sco_year="2020"
|
|
||||||
).get_data(as_text=True)
|
|
||||||
liste_abs2 = sco_abs_views.ListeAbsEtud(
|
|
||||||
etudid, format="json", sco_year="2020"
|
|
||||||
).get_data(as_text=True)
|
|
||||||
|
|
||||||
load_liste_abs = json.loads(liste_abs)
|
|
||||||
load_liste_abs2 = json.loads(liste_abs2)
|
|
||||||
|
|
||||||
assert len(load_liste_abs2) == 1
|
|
||||||
assert len(load_liste_abs) == 2
|
|
||||||
assert load_liste_abs2[0]["ampm"] == 1
|
|
||||||
assert load_liste_abs2[0]["datedmy"] == "22/01/2021"
|
|
||||||
mod = db.session.get(Module, module_id)
|
|
||||||
assert load_liste_abs2[0]["exams"] == mod.code
|
|
||||||
# absjust_only -> seulement les abs justifiés
|
|
||||||
|
|
||||||
# --- Création d'un groupe
|
|
||||||
|
|
||||||
_ = sco_groups.partition_create(
|
|
||||||
formsemestre_id=sem["formsemestre_id"],
|
|
||||||
partition_name="Eleve",
|
|
||||||
)
|
|
||||||
li1 = sco_groups.get_partitions_list(sem["formsemestre_id"])
|
|
||||||
_ = sco_groups.create_group(li1[0]["partition_id"], "Groupe 1")
|
|
||||||
|
|
||||||
# --- Affectation des élèves dans des groupes
|
|
||||||
|
|
||||||
li_grp1 = sco_groups.get_partition_groups(li1[0])
|
|
||||||
for etud in etuds:
|
|
||||||
sco_groups.set_group(etud["etudid"], li_grp1[0]["group_id"])
|
|
||||||
|
|
||||||
# --- Test de EtatAbsencesGroupes
|
|
||||||
|
|
||||||
grp1_abs = absences.EtatAbsencesGr(
|
|
||||||
group_ids=[li_grp1[0]["group_id"]],
|
|
||||||
debut="01/01/2021",
|
|
||||||
fin="30/06/2021",
|
|
||||||
format="json",
|
|
||||||
)
|
|
||||||
# grp1_abs est une Response car on a appelé une vue (1er appel)
|
|
||||||
load_grp1_abs = json.loads(grp1_abs.get_data(as_text=True))
|
|
||||||
|
|
||||||
assert len(load_grp1_abs) == 10
|
|
||||||
|
|
||||||
tab_id = [] # tab des id present dans load_grp1_abs
|
|
||||||
for un_etud in load_grp1_abs:
|
|
||||||
tab_id.append(un_etud["etudid"])
|
|
||||||
|
|
||||||
for (
|
|
||||||
etud
|
|
||||||
) in (
|
|
||||||
etuds
|
|
||||||
): # verification si tous les etudiants sont present dans la liste du groupe d'absence
|
|
||||||
assert etud["etudid"] in tab_id
|
|
||||||
|
|
||||||
for un_etud in load_grp1_abs:
|
|
||||||
if un_etud["etudid"] == etudid:
|
|
||||||
assert un_etud["nbabs"] == 3
|
|
||||||
assert un_etud["nbjustifs_noabs"] == 2
|
|
||||||
assert un_etud["nbabsjust"] == 2
|
|
||||||
assert un_etud["nbabsnonjust"] == 1
|
|
||||||
assert un_etud["nomprenom"] == etuds[0]["nomprenom"]
|
|
||||||
|
|
||||||
# --- Création de billets
|
|
||||||
# Active la gestion de billets:
|
|
||||||
sco_preferences.get_base_preferences().set(None, "handle_billets_abs", 1)
|
|
||||||
|
|
||||||
b1 = absences.AddBilletAbsence(
|
|
||||||
begin="2021-01-22 00:00",
|
|
||||||
end="2021-01-22 23:59",
|
|
||||||
etudid=etudid,
|
|
||||||
description="abs du 22",
|
|
||||||
justified=False,
|
|
||||||
code_nip=etuds[0]["code_nip"],
|
|
||||||
code_ine=etuds[0]["code_ine"],
|
|
||||||
)
|
|
||||||
|
|
||||||
b2 = absences.AddBilletAbsence(
|
|
||||||
begin="2021-01-15 00:00",
|
|
||||||
end="2021-01-15 23:59",
|
|
||||||
etudid=etudid,
|
|
||||||
description="abs du 15",
|
|
||||||
code_nip=etuds[0]["code_nip"],
|
|
||||||
code_ine=etuds[0]["code_ine"],
|
|
||||||
)
|
|
||||||
|
|
||||||
li_bi = absences.billets_etud(etudid=etudid, format="json").get_data(as_text=True)
|
|
||||||
assert isinstance(li_bi, str)
|
|
||||||
load_li_bi = json.loads(li_bi)
|
|
||||||
|
|
||||||
assert len(load_li_bi) == 2
|
|
||||||
assert (
|
|
||||||
load_li_bi[1]["description"] == "abs du 15"
|
|
||||||
or load_li_bi[1]["description"] == "abs du 22"
|
|
||||||
)
|
|
@ -12,7 +12,9 @@ import app.scodoc.sco_assiduites as scass
|
|||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app import db
|
from app import db
|
||||||
from app.models import Assiduite, FormSemestre, Identite, Justificatif, ModuleImpl
|
from app.models import Assiduite, FormSemestre, Identite, Justificatif, ModuleImpl
|
||||||
from app.scodoc import sco_abs_views, sco_formsemestre
|
|
||||||
|
# from app.scodoc import sco_abs_views, sco_formsemestre TODO-ASSIDUITE
|
||||||
|
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
from tests.unit import sco_fake_gen
|
from tests.unit import sco_fake_gen
|
||||||
from tools import downgrade_module, migrate_abs_to_assiduites
|
from tools import downgrade_module, migrate_abs_to_assiduites
|
||||||
@ -36,6 +38,7 @@ def test_bi_directional_enum(test_client):
|
|||||||
assert BiInt.inverse()[1] == BiInt.A and BiInt.inverse()[2] == BiInt.B
|
assert BiInt.inverse()[1] == BiInt.A and BiInt.inverse()[2] == BiInt.B
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip # XXX TODO-ASSIDUITE (issue #690)
|
||||||
def test_general(test_client):
|
def test_general(test_client):
|
||||||
"""tests général du modèle assiduite"""
|
"""tests général du modèle assiduite"""
|
||||||
|
|
||||||
@ -76,7 +79,9 @@ def test_general(test_client):
|
|||||||
date_fin="31/07/2024",
|
date_fin="31/07/2024",
|
||||||
)
|
)
|
||||||
|
|
||||||
formsemestre_1 = sco_formsemestre.get_formsemestre(formsemestre_id_1)
|
formsemestre_1 = sco_formsemestre.get_formsemestre(
|
||||||
|
formsemestre_id_1
|
||||||
|
) # Utiliser plutot FormSemestre de nos jours TODO-ASSIDUITE
|
||||||
formsemestre_2 = sco_formsemestre.get_formsemestre(formsemestre_id_2)
|
formsemestre_2 = sco_formsemestre.get_formsemestre(formsemestre_id_2)
|
||||||
formsemestre_3 = sco_formsemestre.get_formsemestre(formsemestre_id_3)
|
formsemestre_3 = sco_formsemestre.get_formsemestre(formsemestre_id_3)
|
||||||
|
|
||||||
@ -143,6 +148,7 @@ def test_general(test_client):
|
|||||||
editer_supprimer_justificatif(etuds[0])
|
editer_supprimer_justificatif(etuds[0])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip # XXX TODO-ASSIDUITE (issue #696)
|
||||||
def verif_migration_abs_assiduites():
|
def verif_migration_abs_assiduites():
|
||||||
"""Vérification que le script de migration fonctionne correctement"""
|
"""Vérification que le script de migration fonctionne correctement"""
|
||||||
downgrade_module(assiduites=True, justificatifs=True)
|
downgrade_module(assiduites=True, justificatifs=True)
|
||||||
@ -301,7 +307,7 @@ def verif_migration_abs_assiduites():
|
|||||||
False,
|
False,
|
||||||
), # 3 assi 22-23-24/02/2023 08h > 13h (3dj) JUSTI(ext)
|
), # 3 assi 22-23-24/02/2023 08h > 13h (3dj) JUSTI(ext)
|
||||||
]:
|
]:
|
||||||
sco_abs_views.doSignaleAbsence(
|
sco_abs_views.doSignaleAbsence( # TODO-ASSIDUITE
|
||||||
datedebut=debut,
|
datedebut=debut,
|
||||||
datefin=fin,
|
datefin=fin,
|
||||||
demijournee=demijournee,
|
demijournee=demijournee,
|
||||||
|
@ -25,8 +25,6 @@ from app.comp import res_sem
|
|||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import FormSemestre
|
from app.models import FormSemestre
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
from app.scodoc import sco_abs
|
|
||||||
from app.scodoc import sco_abs_views
|
|
||||||
from app.scodoc import sco_bulletins
|
from app.scodoc import sco_bulletins
|
||||||
from app.scodoc import codes_cursus
|
from app.scodoc import codes_cursus
|
||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
@ -188,20 +186,21 @@ def run_sco_basic(verbose=False) -> FormSemestre:
|
|||||||
# -----------------------
|
# -----------------------
|
||||||
etudid = etuds[0]["etudid"]
|
etudid = etuds[0]["etudid"]
|
||||||
|
|
||||||
_ = sco_abs_views.doSignaleAbsence(
|
# XXX TODO-ASSIDUITE
|
||||||
"15/01/2020", "18/01/2020", demijournee=2, etudid=etudid
|
# _ = sco_abs_views.doSignaleAbsence(
|
||||||
)
|
# "15/01/2020", "18/01/2020", demijournee=2, etudid=etudid
|
||||||
|
# )
|
||||||
|
|
||||||
_ = sco_abs_views.doJustifAbsence(
|
# _ = sco_abs_views.doJustifAbsence(
|
||||||
"17/01/2020",
|
# "17/01/2020",
|
||||||
"18/01/2020",
|
# "18/01/2020",
|
||||||
demijournee=2,
|
# demijournee=2,
|
||||||
etudid=etudid,
|
# etudid=etudid,
|
||||||
)
|
# )
|
||||||
|
|
||||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
# nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem)
|
||||||
assert nbabs == 6, f"incorrect nbabs ({nbabs})"
|
# assert nbabs == 6, f"incorrect nbabs ({nbabs})"
|
||||||
assert nbabsjust == 2, f"incorrect nbabsjust ({nbabsjust})"
|
# assert nbabsjust == 2, f"incorrect nbabsjust ({nbabsjust})"
|
||||||
|
|
||||||
# --- Permission saisie notes et décisions de jury, avec ou sans démission ou défaillance
|
# --- Permission saisie notes et décisions de jury, avec ou sans démission ou défaillance
|
||||||
# on n'a pas encore saisi de décisions
|
# on n'a pas encore saisi de décisions
|
||||||
|
Loading…
Reference in New Issue
Block a user