diff --git a/app/static/css/assiduites.css b/app/static/css/assiduites.css
index 1cb99e38..5da0e5d9 100644
--- a/app/static/css/assiduites.css
+++ b/app/static/css/assiduites.css
@@ -449,7 +449,7 @@
transform: translateX(-50%);
}
-.assiduite-infos {
+.assiduite-actions {
position: absolute;
right: 0;
margin: 5px;
diff --git a/app/static/js/assiduites.js b/app/static/js/assiduites.js
index afcc2985..4fa75afa 100644
--- a/app/static/js/assiduites.js
+++ b/app/static/js/assiduites.js
@@ -217,13 +217,11 @@ function creerLigneEtudiant(etud, index) {
const nameField = document.createElement("div");
nameField.classList.add("name_field");
- if ($("#pdp").is(":checked")) {
- const pdp = document.createElement("img");
- pdp.src = `../../api/etudiant/etudid/${etud.id}/photo?size=small`;
- pdp.alt = `${etud.nom} ${etud.prenom}`;
- pdp.classList.add("pdp");
- nameField.appendChild(pdp);
- }
+ const pdp = document.createElement("img");
+ pdp.src = `../../api/etudiant/etudid/${etud.id}/photo?size=small`;
+ pdp.alt = `${etud.nom} ${etud.prenom}`;
+ pdp.classList.add("pdp");
+ nameField.appendChild(pdp);
const nameSet = document.createElement("a");
nameSet.classList.add("name_set");
@@ -857,13 +855,25 @@ function setupAssiduiteBubble(el, assiduite) {
// Ajout d'un lien pour plus d'informations
const infos = document.createElement("a");
- infos.className = "assiduite-infos";
+ infos.className = "";
infos.textContent = `ℹ️`;
infos.title = "Cliquez pour plus d'informations";
infos.target = "_blank";
infos.href = `tableau_assiduite_actions?type=assiduite&action=details&obj_id=${assiduite.assiduite_id}`;
- bubble.appendChild(infos);
+ // Ajout d'un lien pour modifier l'assiduité
+ const modifs = document.createElement("a");
+ modifs.className = "";
+ modifs.textContent = `📝`;
+ modifs.title = "Cliquez pour modifier l'assiduité";
+ modifs.target = "_blank";
+ modifs.href = `tableau_assiduite_actions?type=assiduite&action=modifier&obj_id=${assiduite.assiduite_id}`;
+
+ const actionsDiv = document.createElement("div");
+ actionsDiv.className = "assiduite-actions";
+ actionsDiv.appendChild(modifs);
+ actionsDiv.appendChild(infos);
+ bubble.appendChild(actionsDiv);
const idDiv = document.createElement("div");
idDiv.className = "assiduite-id";
diff --git a/app/tables/liste_assiduites.py b/app/tables/liste_assiduites.py
index 28b347a9..d30c6348 100644
--- a/app/tables/liste_assiduites.py
+++ b/app/tables/liste_assiduites.py
@@ -391,11 +391,11 @@ class RowAssiJusti(tb.Row):
multi_days = self.ligne["date_debut"].date() != self.ligne["date_fin"].date()
date_affichees: list[str] = [
- self.ligne["date_debut"].strftime("%d/%m/%y de %H:%M"), # date début
- self.ligne["date_fin"].strftime("%d/%m/%y de %H:%M"), # date fin
+ self.ligne["date_debut"].strftime("%d/%m/%y %H:%M"), # date début
+ self.ligne["date_fin"].strftime("%d/%m/%y %H:%M"), # date fin
]
- if multi_days:
+ if multi_days and self.ligne["type"] != "justificatif":
date_affichees[0] = self.ligne["date_debut"].strftime("%d/%m/%y")
date_affichees[1] = self.ligne["date_fin"].strftime("%d/%m/%y")
diff --git a/app/templates/assiduites/pages/ajout_justificatif_etud.j2 b/app/templates/assiduites/pages/ajout_justificatif_etud.j2
index e9f725e0..311d25c7 100644
--- a/app/templates/assiduites/pages/ajout_justificatif_etud.j2
+++ b/app/templates/assiduites/pages/ajout_justificatif_etud.j2
@@ -74,8 +74,6 @@ div.submit > input {
{{ form.date_fin.label }} : {{ form.date_fin }}
- si le jour de fin est différent,
- les heures seront ignorées (journées complètes)
{{ render_field_errors(form, 'date_fin') }}
diff --git a/app/templates/assiduites/pages/signal_assiduites_diff.j2 b/app/templates/assiduites/pages/signal_assiduites_diff.j2
index 6847259e..f7b37a21 100644
--- a/app/templates/assiduites/pages/signal_assiduites_diff.j2
+++ b/app/templates/assiduites/pages/signal_assiduites_diff.j2
@@ -20,7 +20,7 @@
#actions {
flex-direction: row;
align-items: center;
- margin-bottom: 5px;
+ margin: 5px 0;
}
#actions label{
margin: 0;
@@ -174,6 +174,48 @@ async function nouvellePeriode(period = null) {
}
}
+ // Vérification de la plage horaire
+ // On génère une date de début et de fin de la période
+ const date_debut = new Date(
+ $("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + debut
+ );
+ const date_fin = new Date(
+ $("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + fin
+ );
+ date_debut.add(1, "seconds");
+
+ // On vérifie que les dates sont valides
+ if (!date_debut.isValid()){
+ const p = document.createElement("p");
+ p.textContent = "La date de début n'est pas valide.";
+ openAlertModal(
+ "Erreur",
+ p,
+ );
+ return;
+ }
+ if (!date_fin.isValid()){
+ const p = document.createElement("p");
+ p.textContent = "La date de fin n'est pas valide.";
+ openAlertModal(
+ "Erreur",
+ p,
+ );
+ return;
+ }
+
+ // On vérifie que l'heure de fin est supérieure à l'heure de début
+ if (date_debut >= date_fin) {
+ const p = document.createElement("p");
+ p.textContent = "La plage horaire n'est pas valide. L'heure de fin doit être "+
+ "supérieure à l'heure de début.";
+ openAlertModal(
+ "Erreur",
+ p,
+ );
+ return;
+ }
+
// On ajoute la nouvelle période au tableau
let periodeDiv = document.createElement("div");
periodeDiv.classList.add("cell", "header");
@@ -211,15 +253,6 @@ async function nouvellePeriode(period = null) {
...document.querySelectorAll(".ligne[data-etudid]"),
].map((e) => e.getAttribute("data-etudid"));
- // On génère une date de début et de fin de la période
- const date_debut = new Date(
- $("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + debut
- );
- const date_fin = new Date(
- $("#date").datepicker("getDate").format("YYYY-MM-DD") + "T" + fin
- );
- date_debut.add(1, "seconds");
-
// Préparation de la requête
const url =
`../../api/assiduites/group/query?date_debut=${date_debut.toFakeIso()}` +
diff --git a/app/templates/assiduites/pages/signal_assiduites_group.j2 b/app/templates/assiduites/pages/signal_assiduites_group.j2
index c3f43af4..bb665b4b 100644
--- a/app/templates/assiduites/pages/signal_assiduites_group.j2
+++ b/app/templates/assiduites/pages/signal_assiduites_group.j2
@@ -54,7 +54,8 @@
}
document.getElementById("pdp").addEventListener("change", (e) => {
- creerTousLesEtudiants(etuds);
+ afficherPDP(e.target.checked);
+ //creerTousLesEtudiants(etuds);
});
$('#date').on('change', async function(d) {
@@ -87,6 +88,8 @@
}
creerTousLesEtudiants(etuds);
+ // affichage ou non des PDP
+ afficherPDP(localStorage.getItem("scodoc-etud-pdp") == "true" )
}
setTimeout(main, 0);
diff --git a/app/templates/scolar/index.j2 b/app/templates/scolar/index.j2
index 0e151691..01bc872f 100644
--- a/app/templates/scolar/index.j2
+++ b/app/templates/scolar/index.j2
@@ -83,6 +83,7 @@ table.semlist tbody tr td.modalite {
padding-right: 1em;
}
+<<<<<<< HEAD
div.modalite {
font-size: 16px;
font-weight: bold;
@@ -147,6 +148,8 @@ span.effectif {
}
+=======
+>>>>>>> b1055a4ebe841f17860d2556cc4b03aa12ec3ab1
{# News #}
diff --git a/app/views/assiduites.py b/app/views/assiduites.py
index 527d0404..cb776994 100644
--- a/app/views/assiduites.py
+++ b/app/views/assiduites.py
@@ -299,7 +299,7 @@ def ajout_assiduite_etud() -> str | Response:
def _get_dates_from_assi_form(
form: AjoutAssiOrJustForm,
- all_day: bool = False,
+ from_justif: bool = False,
) -> tuple[
bool, datetime.datetime | None, datetime.datetime | None, datetime.datetime | None
]:
@@ -327,32 +327,15 @@ def _get_dates_from_assi_form(
date_fin = None
form.set_error("date fin invalide", form.date_fin)
- if date_fin:
- # ignore les heures si plusieurs jours
-
- # Assiduité : garde les heures inscritent dans le formulaire
- # Justificatif : ignore les heures inscrites dans le formulaire (0h -> 23h59)
-
- heure_debut = (
- datetime.time.fromisoformat(debut_jour)
- if not all_day
- else datetime.time(0, 0, 0)
- ) # 0h ou ConfigAssiduite.MorningTime
- heure_fin = (
- datetime.time.fromisoformat(fin_jour)
- if not all_day
- else datetime.time(23, 59, 59)
- ) # 23h59 ou ConfigAssiduite.AfternoonTime
+ if not from_justif and date_fin:
+ # Ne prends pas en compte les heures pour les assiduités sur plusieurs jours
+ heure_debut = datetime.time.fromisoformat(debut_jour)
+ heure_fin = datetime.time.fromisoformat(fin_jour)
else:
try:
- if all_day:
- heure_debut = datetime.time.fromisoformat(
- form.heure_debut.data or "00:00"
- )
- else:
- heure_debut = datetime.time.fromisoformat(
- form.heure_debut.data or debut_jour
- )
+ heure_debut = datetime.time.fromisoformat(
+ form.heure_debut.data or debut_jour
+ )
except ValueError:
form.set_error("heure début invalide", form.heure_debut)
if bool(form.heure_debut.data) != bool(form.heure_fin.data):
@@ -360,10 +343,7 @@ def _get_dates_from_assi_form(
"Les deux heures début et fin doivent être spécifiées, ou aucune"
)
try:
- if all_day:
- heure_fin = datetime.time.fromisoformat(form.heure_fin.data or "23:59")
- else:
- heure_fin = datetime.time.fromisoformat(form.heure_fin.data or fin_jour)
+ heure_fin = datetime.time.fromisoformat(form.heure_fin.data or fin_jour)
except ValueError:
form.set_error("heure fin invalide", form.heure_fin)
@@ -398,6 +378,19 @@ def _get_dates_from_assi_form(
# Ajoute time zone serveur
dt_debut_tz_server = scu.TIME_ZONE.localize(dt_debut)
dt_fin_tz_server = scu.TIME_ZONE.localize(dt_fin)
+
+ if from_justif:
+ cas: list[bool] = [
+ # cas 1 (date de fin vide et pas d'heure de début)
+ not form.date_fin.data and not form.heure_debut.data,
+ # cas 2 (date de fin et pas d'heures)
+ form.date_fin.data != "" and not form.heure_debut.data,
+ ]
+
+ if any(cas):
+ dt_debut_tz_server = dt_debut_tz_server.replace(hour=0, minute=0)
+ dt_fin_tz_server = dt_fin_tz_server.replace(hour=23, minute=59)
+
dt_entry_date_tz_server = (
scu.TIME_ZONE.localize(dt_entry_date) if dt_entry_date else None
)
@@ -753,6 +746,34 @@ def ajout_justificatif_etud():
)
+def _verif_date_form_justif(
+ form: AjoutJustificatifEtudForm, deb: datetime.datetime, fin: datetime.datetime
+) -> tuple[datetime.datetime, datetime.datetime]:
+ """Gère les cas suivants :
+ - si on indique seulement une date de debut : journée 0h-23h59
+ - si on indique date de debut et heures : journée +heure deb/fin
+ (déjà géré par _get_dates_from_assi_form)
+ - Si on indique une date de début et de fin sans heures : Journées 0h-23h59
+ - Si on indique une date de début et de fin avec heures : On fait un objet avec
+ datedeb/heuredeb + datefin/heurefin (déjà géré par _get_dates_from_assi_form)
+ """
+
+ cas: list[bool] = [
+ # cas 1
+ not form.date_fin.data and not form.heure_debut.data,
+ # cas 3
+ form.date_fin.data != "" and not form.heure_debut.data,
+ ]
+
+ if any(cas):
+ deb = deb.replace(hour=0, minute=0)
+ fin = fin.replace(hour=23, minute=59)
+
+ print(f"DEBUG {cas=}")
+
+ return deb, fin
+
+
def _record_justificatif_etud(
etud: Identite, form: AjoutJustificatifEtudForm, justif: Justificatif | None = None
) -> bool:
@@ -769,7 +790,7 @@ def _record_justificatif_etud(
dt_debut_tz_server,
dt_fin_tz_server,
dt_entry_date_tz_server,
- ) = _get_dates_from_assi_form(form, all_day=True)
+ ) = _get_dates_from_assi_form(form, from_justif=True)
if not ok:
log("_record_justificatif_etud: dates invalides")
form.set_error("Erreur: dates invalides")
@@ -831,11 +852,6 @@ def _record_justificatif_etud(
db.session.rollback()
return False
db.session.commit()
- # FIX TEMPORAIRE:
- # on reprend toutes les assiduités et tous les justificatifs
- # pour utiliser le "reset" (remise en "non_just") des assiduités
- # (à terme, il faudrait ne recalculer que les assiduités impactées)
- # VOIR TODO dans compute_assiduites_justified
justif.justifier_assiduites()
scass.simple_invalidate_cache(justif.to_dict(), etud.id)
flash(message)
diff --git a/sco_version.py b/sco_version.py
index e0361b07..9e8a6b24 100644
--- a/sco_version.py
+++ b/sco_version.py
@@ -1,7 +1,11 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
+<<<<<<< HEAD
SCOVERSION = "9.6.955"
+=======
+SCOVERSION = "9.6.954"
+>>>>>>> b1055a4ebe841f17860d2556cc4b03aa12ec3ab1
SCONAME = "ScoDoc"