diff --git a/app/scodoc/sco_evaluation_check_abs.py b/app/scodoc/sco_evaluation_check_abs.py
index 957ba963c..a59cc44c8 100644
--- a/app/scodoc/sco_evaluation_check_abs.py
+++ b/app/scodoc/sco_evaluation_check_abs.py
@@ -30,16 +30,17 @@
from flask import url_for, g
from app import db
-from app.models import Evaluation, FormSemestre, Identite
+from app.models import Evaluation, FormSemestre, Identite, Assiduite
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.sco_exceptions import ScoValueError
from app.scodoc import sco_groups
+from flask_sqlalchemy.query import Query
+from sqlalchemy import or_, and_
+
-# XXX TODO-ASSIDUITE https://scodoc.org/git/ScoDoc/ScoDoc/issues/685
def evaluation_check_absences(evaluation: Evaluation):
"""Vérifie les absences au moment de cette évaluation.
Cas incohérents que l'on peut rencontrer pour chaque étudiant:
@@ -50,28 +51,32 @@ def evaluation_check_absences(evaluation: Evaluation):
EXC et pas justifie
Ramene 5 listes d'etudid
"""
- raise ScoValueError("Fonction non disponible, patience !") # XXX TODO-ASSIDUITE
-
if not evaluation.date_debut:
return [], [], [], [], [] # evaluation sans date
- am, pm = evaluation.is_matin(), evaluation.is_apresmidi()
+ etudids = [
+ etudid
+ for etudid, _ in sco_groups.do_evaluation_listeetuds_groups(
+ evaluation.id, getallstudents=True
+ )
+ ]
- # Liste les absences à ce moment:
- absences = sco_abs.list_abs_jour(evaluation.date_debut, am=am, pm=pm)
- abs_etudids = set([x["etudid"] for x in absences]) # ensemble des etudiants absents
- abs_non_just = sco_abs.list_abs_non_just_jour(
- evaluation.date_debut.date(), am=am, pm=pm
+ deb, fin = scu.localize_datetime(evaluation.date_debut), scu.localize_datetime(
+ evaluation.date_fin
)
- abs_nj_etudids = set(
- [x["etudid"] for x in abs_non_just]
- ) # ensemble des etudiants absents non justifies
- justifs = sco_abs.list_abs_jour(
- evaluation.date_debut.date(), am=am, pm=pm, is_abs=None, is_just=True
+
+ assiduites: Query = Assiduite.query.filter(
+ Assiduite.etudid.in_(etudids),
+ Assiduite.etat == scu.EtatAssiduite.ABSENT,
+ or_(
+ and_(Assiduite.date_debut >= deb, Assiduite.date_debut <= fin),
+ and_(Assiduite.date_fin >= deb, Assiduite.date_fin <= fin),
+ ),
)
- just_etudids = set(
- [x["etudid"] for x in justifs]
- ) # ensemble des etudiants avec justif
+
+ 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)
# Les notes:
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation.id)
@@ -80,9 +85,7 @@ def evaluation_check_absences(evaluation: Evaluation):
ExcNonSignalee = [] # note EXC mais pas noté absent
ExcNonJust = [] # note EXC mais absent non justifie
AbsButExc = [] # note ABS mais justifié
- for etudid, _ in sco_groups.do_evaluation_listeetuds_groups(
- evaluation.id, getallstudents=True
- ):
+ for etudid in etudids:
if etudid in notes_db:
val = notes_db[etudid]["value"]
if (
@@ -170,14 +173,10 @@ def evaluation_check_absences_html(
)
if linkabs:
url = url_for(
- "absences.doSignaleAbsence", # XXX TODO-ASSIDUITE
- scodoc_dept=g.scodoc_dept,
+ "assiduites.signal_evaluation_abs",
etudid=etudid,
- # par defaut signale le jour du début de l'éval
- datedebut=evaluation.date_debut.strftime("%d/%m/%Y"),
- datefin=evaluation.date_debut.strftime("%d/%m/%Y"),
- demijournee=demijournee,
- moduleimpl_id=evaluation.moduleimpl_id,
+ evaluation_id=evaluation.id,
+ scodoc_dept=g.scodoc_dept,
)
H.append(
f"""signaler cette absence"""
diff --git a/app/templates/assiduites/pages/signal_assiduites_etud.j2 b/app/templates/assiduites/pages/signal_assiduites_etud.j2
index 2222cbe42..71dd19962 100644
--- a/app/templates/assiduites/pages/signal_assiduites_etud.j2
+++ b/app/templates/assiduites/pages/signal_assiduites_etud.j2
@@ -32,6 +32,18 @@
+
+ {% if saisie_eval %}
+
+
+
+ La saisie de l'assiduité a été préconfigurée en fonction de l'évaluation.
+ Une fois la saisie finie, cliquez sur le lien si dessous pour revenir sur la gestion de l'évaluation
+
+
retourner sur la page de l'évaluation
+
+ {% endif %}
+
{{diff | safe}}
@@ -118,7 +130,20 @@
window.forceModule = "{{ forcer_module }}"
window.forceModule = window.forceModule == "True" ? true : false
+ const date_deb = "{{date_deb}}";
+ const date_fin = "{{date_fin}}";
+
+ {% if saisie_eval %}
+ createColumn(
+ date_deb,
+ date_fin,
+ {{ moduleimpl_id }}
+ );
+ window.location.href = "#saisie_eval"
+ getAndUpdateCol(1)
+ {% else %}
createColumn();
+ {% endif %}
diff --git a/app/templates/assiduites/widgets/differee.j2 b/app/templates/assiduites/widgets/differee.j2
index 8d96c5bc4..523c4a827 100644
--- a/app/templates/assiduites/widgets/differee.j2
+++ b/app/templates/assiduites/widgets/differee.j2
@@ -278,7 +278,7 @@
currentDate = moment(currentDate).tz(TIMEZONE).format("YYYY-MM-DDTHH:mm");
}
- function createColumn(dateStart = "", dateEnd = "") {
+ function createColumn(dateStart = "", dateEnd = "", moduleimpl_id = "") {
let table = document.getElementById("studentTable");
let th = document.createElement("div");
th.classList.add("th", "error");
@@ -343,6 +343,10 @@
editModuleImpl(sl);
})
+ if (moduleimpl_id != "") {
+ sl.value = moduleimpl_id;
+ }
+
let rows = table.querySelector(".tbody").querySelectorAll(".tr");
for (let i = 0; i < rows.length; i++) {
let td = document.createElement("div");
diff --git a/app/views/assiduites.py b/app/views/assiduites.py
index ebf9dbd31..4e13e8076 100644
--- a/app/views/assiduites.py
+++ b/app/views/assiduites.py
@@ -1,7 +1,7 @@
import datetime
-from flask import g, request, render_template
-from flask import abort, url_for
+from flask import g, request, render_template, flash
+from flask import abort, url_for, redirect
from flask_login import current_user
from app import db
@@ -18,6 +18,7 @@ from app.models import (
Assiduite,
Departement,
FormSemestreInscription,
+ Evaluation,
)
from app.views import assiduites_bp as bp
from app.views import ScoData
@@ -203,6 +204,27 @@ def signal_assiduites_etud():
if etud.dept_id != g.scodoc_dept_id:
abort(404, "étudiant inexistant dans ce département")
+ date = request.args.get("date", datetime.date.today().isoformat())
+
+ # gestion évaluations
+
+ saisie_eval: bool = request.args.get("saisie_eval") is not None
+
+ date_deb: str = request.args.get("date_deb")
+ date_fin: str = request.args.get("date_fin")
+ moduleimpl_id: int = request.args.get("moduleimpl_id", "")
+ evaluation_id: int = request.args.get("evaluation_id")
+
+ redirect_url: str = (
+ "#"
+ if not saisie_eval
+ else url_for(
+ "notes.evaluation_check_absences_html",
+ evaluation_id=evaluation_id,
+ scodoc_dept=g.scodoc_dept,
+ )
+ )
+
header: str = html_sco_header.sco_header(
page_title="Saisie Assiduités",
init_qtip=True,
@@ -235,7 +257,7 @@ def signal_assiduites_etud():
render_template(
"assiduites/pages/signal_assiduites_etud.j2",
sco=ScoData(etud),
- date=datetime.date.today().isoformat(),
+ date=date,
morning=morning,
lunch=lunch,
timeline=_timeline(),
@@ -249,6 +271,11 @@ def signal_assiduites_etud():
etudiants=[sco_etud.get_etud_info(etudid=etud.etudid, filled=True)[0]],
moduleimpl_select=select,
),
+ saisie_eval=saisie_eval,
+ date_deb=date_deb,
+ date_fin=date_fin,
+ redirect_url=redirect_url,
+ moduleimpl_id=moduleimpl_id,
),
).build()
@@ -995,6 +1022,66 @@ def signal_assiduites_diff():
).build()
+@bp.route("/SignalEvaluationAbs//")
+@scodoc
+@permission_required(Permission.ScoView)
+def signal_evaluation_abs(etudid: int = None, evaluation_id: int = None):
+ """
+ Signale l'absence d'un étudiant à une évaluation
+ Si la durée de l'évaluation est inférieur à 1 jour
+ Alors l'absence sera sur la période de l'évaluation
+ Sinon L'utilisateur sera redirigé vers la page de saisie des absences de l'étudiant
+ """
+ etud: Identite = Identite.query.get_or_404(etudid)
+ if etud.dept_id != g.scodoc_dept_id:
+ abort(404, "étudiant inexistant dans ce département")
+
+ evaluation: Evaluation = Evaluation.query.get_or_404(evaluation_id)
+
+ delta: datetime.timedelta = evaluation.date_fin - evaluation.date_debut
+ if delta > datetime.timedelta(days=1):
+ # rediriger vers page saisie
+ flash("Redirection pour saisie abs")
+ return redirect(
+ url_for(
+ "assiduites.signal_assiduites_etud",
+ etudid=etudid,
+ evaluation_id=evaluation.id,
+ date_deb=evaluation.date_debut.strftime("%Y-%m-%dT%H:%M:%S"),
+ date_fin=evaluation.date_fin.strftime("%Y-%m-%dT%H:%M:%S"),
+ moduleimpl_id=evaluation.moduleimpl.id,
+ saisie_eval="true",
+ scodoc_dept=g.scodoc_dept,
+ )
+ )
+
+ # créer l'assiduité
+
+ assiduite_unique: Assiduite = Assiduite.create_assiduite(
+ etud=etud,
+ date_debut=scu.localize_datetime(evaluation.date_debut),
+ date_fin=scu.localize_datetime(evaluation.date_fin),
+ etat=scu.EtatAssiduite.ABSENT,
+ moduleimpl=evaluation.moduleimpl,
+ )
+
+ db.session.add(assiduite_unique)
+ db.session.commit()
+
+ flash("L'absence a bien été créée")
+ # rediriger vers la page d'évaluation
+ return redirect(
+ url_for(
+ "notes.evaluation_check_absences_html",
+ evaluation_id=evaluation.id,
+ scodoc_dept=g.scodoc_dept,
+ )
+ )
+
+
+# --- Fonctions internes ---
+
+
def _get_days_between_dates(deb: str, fin: str):
if deb is None or fin is None:
return "null"