forked from ScoDoc/ScoDoc
Assiduites : evaluation_check_absences #685
This commit is contained in:
parent
c587c8b7d2
commit
cf74708f83
@ -30,16 +30,17 @@
|
|||||||
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, FormSemestre, Identite
|
from app.models import Evaluation, FormSemestre, Identite, Assiduite
|
||||||
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_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
|
||||||
from app.scodoc import sco_groups
|
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):
|
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:
|
||||||
@ -50,28 +51,32 @@ 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
|
||||||
|
|
||||||
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:
|
deb, fin = scu.localize_datetime(evaluation.date_debut), scu.localize_datetime(
|
||||||
absences = sco_abs.list_abs_jour(evaluation.date_debut, am=am, pm=pm)
|
evaluation.date_fin
|
||||||
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
|
|
||||||
)
|
)
|
||||||
abs_nj_etudids = set(
|
|
||||||
[x["etudid"] for x in abs_non_just]
|
assiduites: Query = Assiduite.query.filter(
|
||||||
) # ensemble des etudiants absents non justifies
|
Assiduite.etudid.in_(etudids),
|
||||||
justifs = sco_abs.list_abs_jour(
|
Assiduite.etat == scu.EtatAssiduite.ABSENT,
|
||||||
evaluation.date_debut.date(), am=am, pm=pm, is_abs=None, is_just=True
|
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]
|
abs_etudids = set(assi.etudid for assi in assiduites)
|
||||||
) # ensemble des etudiants avec justif
|
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:
|
# Les notes:
|
||||||
notes_db = sco_evaluation_db.do_evaluation_get_all_notes(evaluation.id)
|
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
|
ExcNonSignalee = [] # note EXC mais pas noté absent
|
||||||
ExcNonJust = [] # note EXC mais absent non justifie
|
ExcNonJust = [] # note EXC mais absent non justifie
|
||||||
AbsButExc = [] # note ABS mais justifié
|
AbsButExc = [] # note ABS mais justifié
|
||||||
for etudid, _ in sco_groups.do_evaluation_listeetuds_groups(
|
for etudid in etudids:
|
||||||
evaluation.id, getallstudents=True
|
|
||||||
):
|
|
||||||
if etudid in notes_db:
|
if etudid in notes_db:
|
||||||
val = notes_db[etudid]["value"]
|
val = notes_db[etudid]["value"]
|
||||||
if (
|
if (
|
||||||
@ -170,14 +173,10 @@ def evaluation_check_absences_html(
|
|||||||
)
|
)
|
||||||
if linkabs:
|
if linkabs:
|
||||||
url = url_for(
|
url = url_for(
|
||||||
"absences.doSignaleAbsence", # XXX TODO-ASSIDUITE
|
"assiduites.signal_evaluation_abs",
|
||||||
scodoc_dept=g.scodoc_dept,
|
|
||||||
etudid=etudid,
|
etudid=etudid,
|
||||||
# par defaut signale le jour du début de l'éval
|
evaluation_id=evaluation.id,
|
||||||
datedebut=evaluation.date_debut.strftime("%d/%m/%Y"),
|
scodoc_dept=g.scodoc_dept,
|
||||||
datefin=evaluation.date_debut.strftime("%d/%m/%Y"),
|
|
||||||
demijournee=demijournee,
|
|
||||||
moduleimpl_id=evaluation.moduleimpl_id,
|
|
||||||
)
|
)
|
||||||
H.append(
|
H.append(
|
||||||
f"""<a class="stdlink" href="{url}">signaler cette absence</a>"""
|
f"""<a class="stdlink" href="{url}">signaler cette absence</a>"""
|
||||||
|
@ -32,6 +32,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
{% if saisie_eval %}
|
||||||
|
<div id="saisie_eval">
|
||||||
|
<br>
|
||||||
|
<h3>
|
||||||
|
La saisie de l'assiduité a été préconfigurée en fonction de l'évaluation. <br>
|
||||||
|
Une fois la saisie finie, cliquez sur le lien si dessous pour revenir sur la gestion de l'évaluation
|
||||||
|
</h3>
|
||||||
|
<a href="{{redirect_url}}">retourner sur la page de l'évaluation</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{{diff | safe}}
|
{{diff | safe}}
|
||||||
|
|
||||||
<div class="legende">
|
<div class="legende">
|
||||||
@ -118,7 +130,20 @@
|
|||||||
window.forceModule = "{{ forcer_module }}"
|
window.forceModule = "{{ forcer_module }}"
|
||||||
window.forceModule = window.forceModule == "True" ? true : false
|
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();
|
createColumn();
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@
|
|||||||
currentDate = moment(currentDate).tz(TIMEZONE).format("YYYY-MM-DDTHH:mm");
|
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 table = document.getElementById("studentTable");
|
||||||
let th = document.createElement("div");
|
let th = document.createElement("div");
|
||||||
th.classList.add("th", "error");
|
th.classList.add("th", "error");
|
||||||
@ -343,6 +343,10 @@
|
|||||||
editModuleImpl(sl);
|
editModuleImpl(sl);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (moduleimpl_id != "") {
|
||||||
|
sl.value = moduleimpl_id;
|
||||||
|
}
|
||||||
|
|
||||||
let rows = table.querySelector(".tbody").querySelectorAll(".tr");
|
let rows = table.querySelector(".tbody").querySelectorAll(".tr");
|
||||||
for (let i = 0; i < rows.length; i++) {
|
for (let i = 0; i < rows.length; i++) {
|
||||||
let td = document.createElement("div");
|
let td = document.createElement("div");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from flask import g, request, render_template
|
from flask import g, request, render_template, flash
|
||||||
from flask import abort, url_for
|
from flask import abort, url_for, redirect
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
@ -18,6 +18,7 @@ from app.models import (
|
|||||||
Assiduite,
|
Assiduite,
|
||||||
Departement,
|
Departement,
|
||||||
FormSemestreInscription,
|
FormSemestreInscription,
|
||||||
|
Evaluation,
|
||||||
)
|
)
|
||||||
from app.views import assiduites_bp as bp
|
from app.views import assiduites_bp as bp
|
||||||
from app.views import ScoData
|
from app.views import ScoData
|
||||||
@ -203,6 +204,27 @@ def signal_assiduites_etud():
|
|||||||
if etud.dept_id != g.scodoc_dept_id:
|
if etud.dept_id != g.scodoc_dept_id:
|
||||||
abort(404, "étudiant inexistant dans ce département")
|
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(
|
header: str = html_sco_header.sco_header(
|
||||||
page_title="Saisie Assiduités",
|
page_title="Saisie Assiduités",
|
||||||
init_qtip=True,
|
init_qtip=True,
|
||||||
@ -235,7 +257,7 @@ def signal_assiduites_etud():
|
|||||||
render_template(
|
render_template(
|
||||||
"assiduites/pages/signal_assiduites_etud.j2",
|
"assiduites/pages/signal_assiduites_etud.j2",
|
||||||
sco=ScoData(etud),
|
sco=ScoData(etud),
|
||||||
date=datetime.date.today().isoformat(),
|
date=date,
|
||||||
morning=morning,
|
morning=morning,
|
||||||
lunch=lunch,
|
lunch=lunch,
|
||||||
timeline=_timeline(),
|
timeline=_timeline(),
|
||||||
@ -249,6 +271,11 @@ def signal_assiduites_etud():
|
|||||||
etudiants=[sco_etud.get_etud_info(etudid=etud.etudid, filled=True)[0]],
|
etudiants=[sco_etud.get_etud_info(etudid=etud.etudid, filled=True)[0]],
|
||||||
moduleimpl_select=select,
|
moduleimpl_select=select,
|
||||||
),
|
),
|
||||||
|
saisie_eval=saisie_eval,
|
||||||
|
date_deb=date_deb,
|
||||||
|
date_fin=date_fin,
|
||||||
|
redirect_url=redirect_url,
|
||||||
|
moduleimpl_id=moduleimpl_id,
|
||||||
),
|
),
|
||||||
).build()
|
).build()
|
||||||
|
|
||||||
@ -995,6 +1022,66 @@ def signal_assiduites_diff():
|
|||||||
).build()
|
).build()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/SignalEvaluationAbs/<int:evaluation_id>/<int:etudid>")
|
||||||
|
@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):
|
def _get_days_between_dates(deb: str, fin: str):
|
||||||
if deb is None or fin is None:
|
if deb is None or fin is None:
|
||||||
return "null"
|
return "null"
|
||||||
|
Loading…
Reference in New Issue
Block a user