ScoDoc/app/scodoc/sco_evaluation_check_abs.py

253 lines
9.2 KiB
Python
Raw Normal View History

2021-11-20 17:53:21 +01:00
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
2023-01-02 13:16:27 +01:00
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
2021-11-20 17:53:21 +01: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
#
##############################################################################
"""Vérification des absences à une évaluation
2021-11-20 17:53:21 +01:00
"""
from flask import url_for, g
2023-12-10 20:59:32 +01:00
from flask_sqlalchemy.query import Query
2021-11-20 17:53:21 +01:00
2023-08-25 17:58:57 +02:00
from app import db
from app.models import Evaluation, FormSemestre, Identite, Assiduite
2021-11-20 17:53:21 +01:00
import app.scodoc.sco_utils as scu
from app.scodoc import html_sco_header
from app.scodoc import sco_evaluations
from app.scodoc import sco_evaluation_db
from app.scodoc import sco_groups
2023-08-25 17:58:57 +02:00
def evaluation_check_absences(evaluation: Evaluation):
2021-11-20 17:53:21 +01:00
"""Vérifie les absences au moment de cette évaluation.
Cas incohérents que l'on peut rencontrer pour chaque étudiant:
note et absent
ABS et pas noté absent
ABS et absent justifié
EXC et pas noté absent
EXC et pas justifie
2023-08-25 17:58:57 +02:00
Ramene 5 listes d'etudid
2021-11-20 17:53:21 +01:00
"""
if not evaluation.date_debut or not evaluation.date_fin:
2021-11-20 17:53:21 +01:00
return [], [], [], [], [] # evaluation sans date
etudids = [
etudid
for etudid, _ in sco_groups.do_evaluation_listeetuds_groups(
evaluation.id, getallstudents=True
)
]
2021-11-20 17:53:21 +01:00
deb, fin = scu.localize_datetime(evaluation.date_debut), scu.localize_datetime(
evaluation.date_fin
2023-08-25 17:58:57 +02:00
)
assiduites: Query = Assiduite.query.filter(
Assiduite.etudid.in_(etudids),
Assiduite.etat == scu.EtatAssiduite.ABSENT,
fin >= Assiduite.date_debut,
deb <= Assiduite.date_fin,
2021-11-20 17:53:21 +01:00
)
abs_etudids = set(assi.etudid for assi in assiduites)
abs_nj_etudids = set(assi.etudid for assi in assiduites if assi.est_just is False)
just_etudids = set(assi.etudid for assi in assiduites if assi.est_just is True)
2021-11-20 17:53:21 +01:00
# Les notes:
2023-08-25 17:58:57 +02:00
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation.id)
2023-12-10 20:59:32 +01:00
note_but_abs = [] # une note mais noté absent
abs_non_signalee = [] # note ABS mais pas noté absent
exc_non_signalee = [] # note EXC mais pas noté absent
exc_non_just = [] # note EXC mais absent non justifie
abs_but_exc = [] # note ABS mais justifié
for etudid in etudids:
2022-01-17 00:18:08 +01:00
if etudid in notes_db:
val = notes_db[etudid]["value"]
2021-11-20 17:53:21 +01:00
if (
2023-08-25 17:58:57 +02:00
val is not None
and val != scu.NOTES_NEUTRALISE
and val != scu.NOTES_ATTENTE
) and etudid in abs_etudids:
2021-11-20 17:53:21 +01:00
# note valide et absent
2023-12-10 20:59:32 +01:00
note_but_abs.append(etudid)
2023-08-25 17:58:57 +02:00
if val is None and not etudid in abs_etudids:
2021-11-20 17:53:21 +01:00
# absent mais pas signale comme tel
2023-12-10 20:59:32 +01:00
abs_non_signalee.append(etudid)
2023-08-25 17:58:57 +02:00
if val == scu.NOTES_NEUTRALISE and not etudid in abs_etudids:
2021-11-20 17:53:21 +01:00
# Neutralisé mais pas signale absent
2023-12-10 20:59:32 +01:00
exc_non_signalee.append(etudid)
2023-08-25 17:58:57 +02:00
if val == scu.NOTES_NEUTRALISE and etudid in abs_nj_etudids:
2021-11-20 17:53:21 +01:00
# EXC mais pas justifié
2023-12-10 20:59:32 +01:00
exc_non_just.append(etudid)
2023-08-25 17:58:57 +02:00
if val is None and etudid in just_etudids:
2021-11-20 17:53:21 +01:00
# ABS mais justificatif
2023-12-10 20:59:32 +01:00
abs_but_exc.append(etudid)
2021-11-20 17:53:21 +01:00
2023-12-10 20:59:32 +01:00
return note_but_abs, abs_non_signalee, exc_non_signalee, exc_non_just, abs_but_exc
2021-11-20 17:53:21 +01:00
2023-09-06 08:48:00 +02:00
def evaluation_check_absences_html(
evaluation: Evaluation, with_header=True, show_ok=True
):
2021-11-20 17:53:21 +01:00
"""Affiche état vérification absences d'une évaluation"""
(
2023-12-10 20:59:32 +01:00
note_but_abs, # une note alors qu'il était signalé abs
abs_non_signalee, # note ABS alors que pas signalé abs
exc_non_signalee, # note EXC alors que pas signalé abs
exc_non_just, # note EXC alors que pas de justif
abs_but_exc, # note ABS alors qu'il y a un justif
2023-08-25 17:58:57 +02:00
) = evaluation_check_absences(evaluation)
2021-11-20 17:53:21 +01:00
if with_header:
H = [
2023-12-10 20:59:32 +01:00
html_sco_header.html_sem_header(
"Vérification absences à l'évaluation",
formsemestre_id=evaluation.moduleimpl.formsemestre_id,
),
2023-08-25 17:58:57 +02:00
sco_evaluations.evaluation_describe(evaluation_id=evaluation.id),
2023-12-10 20:59:32 +01:00
"""<p class="help">Vérification de la cohérence entre les notes saisies
2023-08-25 17:58:57 +02:00
et les absences signalées.</p>""",
2021-11-20 17:53:21 +01:00
]
else:
# pas de header, mais un titre
H = [
2023-08-25 17:58:57 +02:00
f"""<h2 class="eval_check_absences">{
evaluation.description or "évaluation"
} du {
evaluation.date_debut.strftime("%d/%m/%Y") if evaluation.date_debut else ""
} """
2021-11-20 17:53:21 +01:00
]
if (
2023-12-10 20:59:32 +01:00
not note_but_abs
and not abs_non_signalee
and not exc_non_signalee
and not exc_non_just
2021-11-20 17:53:21 +01:00
):
H.append(': <span class="eval_check_absences_ok">ok</span>')
H.append("</h2>")
def etudlist(etudids, linkabs=False):
H.append("<ul>")
if not etudids and show_ok:
H.append("<li>aucun</li>")
for etudid in etudids:
2023-08-25 17:58:57 +02:00
etud: Identite = db.session.get(Identite, etudid)
2021-11-20 17:53:21 +01:00
H.append(
2023-08-25 17:58:57 +02:00
f"""<li><a class="discretelink" href="{
url_for(
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid
)
}">{etud.nomprenom}</a>"""
2021-11-20 17:53:21 +01:00
)
if linkabs:
2023-08-25 17:58:57 +02:00
url = url_for(
2023-12-10 20:59:32 +01:00
"assiduites.signale_evaluation_abs",
2023-08-25 17:58:57 +02:00
etudid=etudid,
evaluation_id=evaluation.id,
scodoc_dept=g.scodoc_dept,
2023-08-25 17:58:57 +02:00
)
H.append(
2023-12-10 20:59:32 +01:00
f"""<a style="margin-left: 16px;" class="stdlink" href="{
url}">signaler cette absence</a>"""
2021-11-20 17:53:21 +01:00
)
H.append("</li>")
H.append("</ul>")
2023-12-10 20:59:32 +01:00
if note_but_abs or show_ok:
2021-11-20 17:53:21 +01:00
H.append(
2023-12-10 20:59:32 +01:00
"<h3>Étudiants ayant une note alors qu'ils sont signalés absents:</h3>"
2021-11-20 17:53:21 +01:00
)
2023-12-10 20:59:32 +01:00
etudlist(note_but_abs)
2021-11-20 17:53:21 +01:00
2023-12-10 20:59:32 +01:00
if abs_non_signalee or show_ok:
2021-11-20 17:53:21 +01:00
H.append(
2023-12-10 20:59:32 +01:00
"""<h3>Étudiants avec note "ABS" alors qu'ils ne sont
<em>pas</em> signalés absents:</h3>"""
2021-11-20 17:53:21 +01:00
)
2023-12-10 20:59:32 +01:00
etudlist(abs_non_signalee, linkabs=True)
2021-11-20 17:53:21 +01:00
2023-12-10 20:59:32 +01:00
if exc_non_signalee or show_ok:
2021-11-20 17:53:21 +01:00
H.append(
2023-12-10 20:59:32 +01:00
"""<h3>Étudiants avec note "EXC" alors qu'ils ne sont
<em>pas</em> signalés absents:</h3>"""
2021-11-20 17:53:21 +01:00
)
2023-12-10 20:59:32 +01:00
etudlist(exc_non_signalee)
2021-11-20 17:53:21 +01:00
2023-12-10 20:59:32 +01:00
if exc_non_just or show_ok:
2021-11-20 17:53:21 +01:00
H.append(
2023-12-10 20:59:32 +01:00
"""<h3>Étudiants avec note "EXC" alors qu'ils sont absents
<em>non justifiés</em>:</h3>"""
2021-11-20 17:53:21 +01:00
)
2023-12-10 20:59:32 +01:00
etudlist(exc_non_just)
2021-11-20 17:53:21 +01:00
2023-12-10 20:59:32 +01:00
if abs_but_exc or show_ok:
2021-11-20 17:53:21 +01:00
H.append(
2023-12-10 20:59:32 +01:00
"""<h3>Étudiants avec note "ABS" alors qu'ils ont une <em>justification</em>:</h3>"""
2021-11-20 17:53:21 +01:00
)
2023-12-10 20:59:32 +01:00
etudlist(abs_but_exc)
2021-11-20 17:53:21 +01:00
if with_header:
H.append(html_sco_header.sco_footer())
return "\n".join(H)
def formsemestre_check_absences_html(formsemestre_id):
"""Affiche etat verification absences pour toutes les evaluations du semestre !"""
formsemestre: FormSemestre = FormSemestre.query.filter_by(
dept_id=g.scodoc_dept_id, id=formsemestre_id
).first_or_404()
2021-11-20 17:53:21 +01:00
H = [
html_sco_header.html_sem_header(
"Vérification absences aux évaluations de ce semestre",
),
2023-12-10 20:59:32 +01:00
"""<p class="help">Vérification de la cohérence entre les notes saisies
et les absences signalées.
Sont listés tous les modules avec des évaluations.<br>Aucune action n'est effectuée:
2021-11-20 17:53:21 +01:00
il vous appartient de corriger les erreurs détectées si vous le jugez nécessaire.
</p>""",
]
# Modules, dans l'ordre
for modimpl in formsemestre.modimpls_sorted:
if modimpl.evaluations.count() > 0:
2021-11-20 17:53:21 +01:00
H.append(
f"""<div class="module_check_absences">
<h2><a href="{
2023-12-10 20:59:32 +01:00
url_for("notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, moduleimpl_id=modimpl.id)
}">{modimpl.module.code or ""}: {modimpl.module.abbrev or ""}</a>
</h2>"""
2021-11-20 17:53:21 +01:00
)
2023-12-10 20:59:32 +01:00
for evaluation in modimpl.evaluations:
H.append(
evaluation_check_absences_html(
2023-09-06 08:48:00 +02:00
evaluation,
with_header=False,
show_ok=False,
)
2021-11-20 17:53:21 +01:00
)
H.append("</div>")
2021-11-20 17:53:21 +01:00
H.append(html_sco_header.sco_footer())
return "\n".join(H)