forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -27,7 +27,7 @@ from app.models import (
|
|||||||
Justificatif,
|
Justificatif,
|
||||||
)
|
)
|
||||||
from flask_sqlalchemy.query import Query
|
from flask_sqlalchemy.query import Query
|
||||||
from app.models.assiduites import get_assiduites_justif
|
from app.models.assiduites import get_assiduites_justif, get_justifs_from_date
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
from app.scodoc.sco_utils import json_error
|
from app.scodoc.sco_utils import json_error
|
||||||
@ -728,7 +728,6 @@ def assiduite_edit(assiduite_id: int):
|
|||||||
assiduite_unique.etudiant.id,
|
assiduite_unique.etudiant.id,
|
||||||
msg=f"assiduite: modif {assiduite_unique}",
|
msg=f"assiduite: modif {assiduite_unique}",
|
||||||
)
|
)
|
||||||
db.session.add(assiduite_unique)
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
scass.simple_invalidate_cache(assiduite_unique.to_dict())
|
scass.simple_invalidate_cache(assiduite_unique.to_dict())
|
||||||
|
|
||||||
@ -848,15 +847,23 @@ def _edit_singular(assiduite_unique, data):
|
|||||||
# Cas 3 : desc
|
# Cas 3 : desc
|
||||||
desc = data.get("desc", False)
|
desc = data.get("desc", False)
|
||||||
if desc is not False:
|
if desc is not False:
|
||||||
assiduite_unique.desc = desc
|
assiduite_unique.description = desc
|
||||||
|
|
||||||
# Cas 4 : est_just
|
# Cas 4 : est_just
|
||||||
est_just = data.get("est_just")
|
if assiduite_unique.etat == scu.EtatAssiduite.PRESENT:
|
||||||
if est_just is not None:
|
assiduite_unique.est_just = False
|
||||||
if not isinstance(est_just, bool):
|
|
||||||
errors.append("param 'est_just' : booléen non reconnu")
|
|
||||||
else:
|
else:
|
||||||
assiduite_unique.est_just = est_just
|
assiduite_unique.est_just = (
|
||||||
|
len(
|
||||||
|
get_justifs_from_date(
|
||||||
|
assiduite_unique.etudiant.id,
|
||||||
|
assiduite_unique.date_debut,
|
||||||
|
assiduite_unique.date_fin,
|
||||||
|
valid=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
> 0
|
||||||
|
)
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
err: str = ", ".join(errors)
|
err: str = ", ".join(errors)
|
||||||
@ -1024,6 +1031,19 @@ def _filter_manager(requested, assiduites_query: Query) -> Query:
|
|||||||
if user_id is not False:
|
if user_id is not False:
|
||||||
assiduites_query: Query = scass.filter_by_user_id(assiduites_query, user_id)
|
assiduites_query: Query = scass.filter_by_user_id(assiduites_query, user_id)
|
||||||
|
|
||||||
|
order = requested.args.get("order", None)
|
||||||
|
if order is not None:
|
||||||
|
assiduites_query: Query = assiduites_query.order_by(Assiduite.date_debut.desc())
|
||||||
|
|
||||||
|
courant = requested.args.get("courant", None)
|
||||||
|
if courant is not None:
|
||||||
|
annee: int = scu.annee_scolaire()
|
||||||
|
|
||||||
|
assiduites_query: Query = assiduites_query.filter(
|
||||||
|
Assiduite.date_debut >= scu.date_debut_anne_scolaire(annee),
|
||||||
|
Assiduite.date_fin <= scu.date_fin_anne_scolaire(annee),
|
||||||
|
)
|
||||||
|
|
||||||
return assiduites_query
|
return assiduites_query
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,6 +130,8 @@ def justificatifs(etudid: int = None, nip=None, ine=None, with_query: bool = Fal
|
|||||||
@api_web_bp.route(
|
@api_web_bp.route(
|
||||||
"/justificatifs/dept/<int:dept_id>/query", defaults={"with_query": True}
|
"/justificatifs/dept/<int:dept_id>/query", defaults={"with_query": True}
|
||||||
)
|
)
|
||||||
|
@bp.route("/justificatifs/dept/<int:dept_id>", defaults={"with_query": False})
|
||||||
|
@bp.route("/justificatifs/dept/<int:dept_id>/query", defaults={"with_query": True})
|
||||||
@login_required
|
@login_required
|
||||||
@scodoc
|
@scodoc
|
||||||
@as_json
|
@as_json
|
||||||
@ -151,6 +153,48 @@ def justificatifs_dept(dept_id: int = None, with_query: bool = False):
|
|||||||
return data_set
|
return data_set
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route(
|
||||||
|
"/justificatifs/formsemestre/<int:formsemestre_id>", defaults={"with_query": False}
|
||||||
|
)
|
||||||
|
@api_web_bp.route(
|
||||||
|
"/justificatifs/formsemestre/<int:formsemestre_id>", defaults={"with_query": False}
|
||||||
|
)
|
||||||
|
@bp.route(
|
||||||
|
"/justificatifs/formsemestre/<int:formsemestre_id>/query",
|
||||||
|
defaults={"with_query": True},
|
||||||
|
)
|
||||||
|
@api_web_bp.route(
|
||||||
|
"/justificatifs/formsemestre/<int:formsemestre_id>/query",
|
||||||
|
defaults={"with_query": True},
|
||||||
|
)
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@as_json
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def justificatifs_formsemestre(formsemestre_id: int, with_query: bool = False):
|
||||||
|
"""Retourne tous les justificatifs du formsemestre"""
|
||||||
|
formsemestre: FormSemestre = None
|
||||||
|
formsemestre_id = int(formsemestre_id)
|
||||||
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
|
||||||
|
|
||||||
|
if formsemestre is None:
|
||||||
|
return json_error(404, "le paramètre 'formsemestre_id' n'existe pas")
|
||||||
|
|
||||||
|
justificatifs_query = scass.filter_by_formsemestre(
|
||||||
|
Justificatif.query, Justificatif, formsemestre
|
||||||
|
)
|
||||||
|
|
||||||
|
if with_query:
|
||||||
|
justificatifs_query = _filter_manager(request, justificatifs_query)
|
||||||
|
|
||||||
|
data_set: list[dict] = []
|
||||||
|
for justi in justificatifs_query.all():
|
||||||
|
data = justi.to_dict(format_api=True)
|
||||||
|
data_set.append(data)
|
||||||
|
|
||||||
|
return data_set
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
@bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
||||||
@api_web_bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
@api_web_bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
||||||
@bp.route("/justificatif/etudid/<etudid>/create", methods=["POST"])
|
@bp.route("/justificatif/etudid/<etudid>/create", methods=["POST"])
|
||||||
@ -696,4 +740,19 @@ def _filter_manager(requested, justificatifs_query):
|
|||||||
justificatifs_query, Justificatif, formsemestre
|
justificatifs_query, Justificatif, formsemestre
|
||||||
)
|
)
|
||||||
|
|
||||||
|
order = requested.args.get("order", None)
|
||||||
|
if order is not None:
|
||||||
|
justificatifs_query: Query = justificatifs_query.order_by(
|
||||||
|
Justificatif.date_debut.desc()
|
||||||
|
)
|
||||||
|
|
||||||
|
courant = requested.args.get("courant", None)
|
||||||
|
if courant is not None:
|
||||||
|
annee: int = scu.annee_scolaire()
|
||||||
|
|
||||||
|
justificatifs_query: Query = justificatifs_query.filter(
|
||||||
|
Justificatif.date_debut >= scu.date_debut_anne_scolaire(annee),
|
||||||
|
Justificatif.date_fin <= scu.date_fin_anne_scolaire(annee),
|
||||||
|
)
|
||||||
|
|
||||||
return justificatifs_query
|
return justificatifs_query
|
||||||
|
@ -134,7 +134,10 @@ class Assiduite(db.Model):
|
|||||||
|
|
||||||
if not est_just:
|
if not est_just:
|
||||||
est_just = (
|
est_just = (
|
||||||
len(_get_assiduites_justif(etud.etudid, date_debut, date_fin)) > 0
|
len(
|
||||||
|
get_justifs_from_date(etud.etudid, date_debut, date_fin, valid=True)
|
||||||
|
)
|
||||||
|
> 0
|
||||||
)
|
)
|
||||||
|
|
||||||
if moduleimpl is not None:
|
if moduleimpl is not None:
|
||||||
@ -375,16 +378,23 @@ def compute_assiduites_justified(
|
|||||||
|
|
||||||
def get_assiduites_justif(assiduite_id: int, long: bool):
|
def get_assiduites_justif(assiduite_id: int, long: bool):
|
||||||
assi: Assiduite = Assiduite.query.get_or_404(assiduite_id)
|
assi: Assiduite = Assiduite.query.get_or_404(assiduite_id)
|
||||||
return _get_assiduites_justif(assi.etudid, assi.date_debut, assi.date_fin, long)
|
return get_justifs_from_date(assi.etudid, assi.date_debut, assi.date_fin, long)
|
||||||
|
|
||||||
|
|
||||||
def _get_assiduites_justif(
|
def get_justifs_from_date(
|
||||||
etudid: int, date_debut: datetime, date_fin: datetime, long: bool = False
|
etudid: int,
|
||||||
|
date_debut: datetime,
|
||||||
|
date_fin: datetime,
|
||||||
|
long: bool = False,
|
||||||
|
valid: bool = False,
|
||||||
):
|
):
|
||||||
justifs: Justificatif = Justificatif.query.filter(
|
justifs: Query = Justificatif.query.filter(
|
||||||
Justificatif.etudid == etudid,
|
Justificatif.etudid == etudid,
|
||||||
Justificatif.date_debut <= date_debut,
|
Justificatif.date_debut <= date_debut,
|
||||||
Justificatif.date_fin >= date_fin,
|
Justificatif.date_fin >= date_fin,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if valid:
|
||||||
|
justifs = justifs.filter(Justificatif.etat == EtatJustificatif.VALIDE)
|
||||||
|
|
||||||
return [j.justif_id if not long else j.to_dict(True) for j in justifs]
|
return [j.justif_id if not long else j.to_dict(True) for j in justifs]
|
||||||
|
@ -311,7 +311,7 @@ def filter_by_date(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def filter_justificatifs_by_etat(justificatifs: Justificatif, etat: str) -> Query:
|
def filter_justificatifs_by_etat(justificatifs: Query, etat: str) -> Query:
|
||||||
"""
|
"""
|
||||||
Filtrage d'une collection de justificatifs en fonction de leur état
|
Filtrage d'une collection de justificatifs en fonction de leur état
|
||||||
"""
|
"""
|
||||||
|
@ -610,6 +610,17 @@ class BasePreferences:
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
# Assiduités
|
# Assiduités
|
||||||
|
(
|
||||||
|
"assi_limit_annee",
|
||||||
|
{
|
||||||
|
"initvalue": 1,
|
||||||
|
"title": "Ne lister que les assiduités de l'année",
|
||||||
|
"explanation": "Limite l'affichage des listes d'assiduités et de justificatifs à l'année en cours",
|
||||||
|
"input_type": "boolcheckbox",
|
||||||
|
"labels": ["non", "oui"],
|
||||||
|
"category": "assi",
|
||||||
|
},
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"forcer_module",
|
"forcer_module",
|
||||||
{
|
{
|
||||||
|
@ -1107,6 +1107,7 @@ def _get_sorted_etuds(evaluation: Evaluation, etudids: list, formsemestre_id: in
|
|||||||
evaluation.date_debut.date().isoformat() if evaluation.date_debut else ""
|
evaluation.date_debut.date().isoformat() if evaluation.date_debut else ""
|
||||||
)
|
)
|
||||||
warn_abs_lst = []
|
warn_abs_lst = []
|
||||||
|
# XXX TODO-ASSIDUITE (issue #686)
|
||||||
if evaluation.is_matin():
|
if evaluation.is_matin():
|
||||||
nbabs = 0 # TODO-ASSIDUITE 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 = 0 # TODO-ASSIDUITE 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)
|
||||||
|
@ -136,6 +136,8 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
margin: 0 5%;
|
margin: 0 5%;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.etud_row.def .nom::after,
|
.etud_row.def .nom::after,
|
||||||
@ -268,6 +270,7 @@
|
|||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.rbtn.present::before {
|
.rbtn.present::before {
|
||||||
background-image: url(../icons/present.svg);
|
background-image: url(../icons/present.svg);
|
||||||
}
|
}
|
||||||
@ -285,8 +288,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.rbtn:checked:before {
|
.rbtn:checked:before {
|
||||||
outline: 3px solid #7059FF;
|
outline: 5px solid #7059FF;
|
||||||
border-radius: 5px;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rbtn:focus {
|
.rbtn:focus {
|
||||||
|
@ -1065,8 +1065,22 @@ function actualizeEtudAssiduite(etudid) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllAssiduitesFromEtud(etudid, action) {
|
function getAllAssiduitesFromEtud(
|
||||||
const url_api = getUrl() + `/api/assiduites/${etudid}`;
|
etudid,
|
||||||
|
action,
|
||||||
|
order = false,
|
||||||
|
justifs = false,
|
||||||
|
courant = false
|
||||||
|
) {
|
||||||
|
const url_api =
|
||||||
|
getUrl() +
|
||||||
|
`/api/assiduites/${etudid}${
|
||||||
|
order
|
||||||
|
? "/query?order%°"
|
||||||
|
.replace("%", justifs ? "&with_justifs" : "")
|
||||||
|
.replace("°", courant ? "&courant" : "")
|
||||||
|
: ""
|
||||||
|
}`;
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
async: true,
|
async: true,
|
||||||
@ -1240,12 +1254,10 @@ function generateEtudRow(
|
|||||||
|
|
||||||
<img class="pdp" src="${pdp_url}">
|
<img class="pdp" src="${pdp_url}">
|
||||||
|
|
||||||
<div class="name_set">
|
<a class="name_set" href="BilanEtud?etudid=${etud.id}">
|
||||||
|
|
||||||
<h4 class="nom">${etud.nom}</h4>
|
<h4 class="nom">${etud.nom}</h4>
|
||||||
<h5 class="prenom">${etud.prenom}</h5>
|
<h5 class="prenom">${etud.prenom}</h5>
|
||||||
|
</a>
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="assiduites_bar">
|
<div class="assiduites_bar">
|
||||||
@ -1558,20 +1570,18 @@ function fastJustify(assiduite) {
|
|||||||
//créer justificatif
|
//créer justificatif
|
||||||
|
|
||||||
const justif = {
|
const justif = {
|
||||||
date_debut: new moment.tz(assiduite.date_debut, TIMEZONE)
|
date_debut: new moment.tz(assiduite.date_debut, TIMEZONE).format(),
|
||||||
.add(1, "s")
|
date_fin: new moment.tz(assiduite.date_fin, TIMEZONE).format(),
|
||||||
.format(),
|
|
||||||
date_fin: new moment.tz(assiduite.date_fin, TIMEZONE)
|
|
||||||
.subtract(1, "s")
|
|
||||||
.format(),
|
|
||||||
raison: raison,
|
raison: raison,
|
||||||
etat: etat,
|
etat: etat,
|
||||||
};
|
};
|
||||||
|
|
||||||
createJustificatif(justif);
|
createJustificatif(justif);
|
||||||
|
|
||||||
// justifyAssiduite(assiduite.assiduite_id, true);
|
|
||||||
generateAllEtudRow();
|
generateAllEtudRow();
|
||||||
|
try {
|
||||||
|
loadAll();
|
||||||
|
} catch {}
|
||||||
};
|
};
|
||||||
|
|
||||||
const content = document.createElement("fieldset");
|
const content = document.createElement("fieldset");
|
||||||
@ -1634,8 +1644,17 @@ function createJustificatif(justif, success = () => {}) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllJustificatifsFromEtud(etudid, action) {
|
function getAllJustificatifsFromEtud(
|
||||||
const url_api = getUrl() + `/api/justificatifs/${etudid}`;
|
etudid,
|
||||||
|
action,
|
||||||
|
order = false,
|
||||||
|
courant = false
|
||||||
|
) {
|
||||||
|
const url_api =
|
||||||
|
getUrl() +
|
||||||
|
`/api/justificatifs/${etudid}${
|
||||||
|
order ? "/query?order°".replace("°", courant ? "&courant" : "") : ""
|
||||||
|
}`;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
async: true,
|
async: true,
|
||||||
type: "GET",
|
type: "GET",
|
||||||
|
@ -114,9 +114,18 @@ class RowAssi(tb.Row):
|
|||||||
|
|
||||||
compte_justificatifs = scass.filter_by_date(
|
compte_justificatifs = scass.filter_by_date(
|
||||||
etud.justificatifs, Justificatif, self.dates[0], self.dates[1]
|
etud.justificatifs, Justificatif, self.dates[0], self.dates[1]
|
||||||
).count()
|
)
|
||||||
|
|
||||||
self.add_cell("justificatifs", "Justificatifs", f"{compte_justificatifs}")
|
compte_justificatifs_att = compte_justificatifs.filter(Justificatif.etat == 2)
|
||||||
|
|
||||||
|
self.add_cell(
|
||||||
|
"justificatifs_att",
|
||||||
|
"Justificatifs en Attente",
|
||||||
|
f"{compte_justificatifs_att.count()}",
|
||||||
|
)
|
||||||
|
self.add_cell(
|
||||||
|
"justificatifs", "Justificatifs", f"{compte_justificatifs.count()}"
|
||||||
|
)
|
||||||
|
|
||||||
def _get_etud_stats(self, etud: Identite) -> dict[str, list[str, float, float]]:
|
def _get_etud_stats(self, etud: Identite) -> dict[str, list[str, float, float]]:
|
||||||
retour: dict[str, tuple[str, float, float]] = {
|
retour: dict[str, tuple[str, float, float]] = {
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
<div class="justi-label">
|
<div class="justi-label">
|
||||||
<legend for="justi_date_debut" required>Date de début</legend>
|
<legend for="justi_date_debut" required>Date de début</legend>
|
||||||
<input type="datetime-local" name="justi_date_debut" id="justi_date_debut">
|
<input type="datetime-local" name="justi_date_debut" id="justi_date_debut">
|
||||||
|
<span>Journée entière</span> <input type="checkbox" name="justi_journee" id="justi_journee">
|
||||||
</div>
|
</div>
|
||||||
<div class="justi-label">
|
<div class="justi-label" id="date_fin">
|
||||||
<legend for="justi_date_fin" required>Date de fin</legend>
|
<legend for="justi_date_fin" required>Date de fin</legend>
|
||||||
<input type="datetime-local" name="justi_date_fin" id="justi_date_fin">
|
<input type="datetime-local" name="justi_date_fin" id="justi_date_fin">
|
||||||
</div>
|
</div>
|
||||||
@ -110,16 +111,15 @@
|
|||||||
|
|
||||||
function validateFields() {
|
function validateFields() {
|
||||||
const field = document.querySelector('.justi-form')
|
const field = document.querySelector('.justi-form')
|
||||||
const in_date_debut = field.querySelector('#justi_date_debut');
|
const { deb, fin } = getDates()
|
||||||
const in_date_fin = field.querySelector('#justi_date_fin');
|
|
||||||
|
|
||||||
if (in_date_debut.value == "" || in_date_fin.value == "") {
|
if (deb.value == "" || fin.value == "") {
|
||||||
openAlertModal("Erreur détéctée", document.createTextNode("Il faut indiquer une date de début et une date de fin."), "", color = "crimson");
|
openAlertModal("Erreur détéctée", document.createTextNode("Il faut indiquer une date de début et une date de fin."), "", color = "crimson");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const date_debut = moment.tz(in_date_debut.value, TIMEZONE);
|
const date_debut = moment.tz(deb.value, TIMEZONE);
|
||||||
const date_fin = moment.tz(in_date_fin.value, TIMEZONE);
|
const date_fin = moment.tz(fin.value, TIMEZONE);
|
||||||
|
|
||||||
if (date_fin.isBefore(date_debut)) {
|
if (date_fin.isBefore(date_debut)) {
|
||||||
openAlertModal("Erreur détéctée", document.createTextNode("La date de fin doit se trouver après la date de début."), "", color = "crimson");
|
openAlertModal("Erreur détéctée", document.createTextNode("La date de fin doit se trouver après la date de début."), "", color = "crimson");
|
||||||
@ -132,14 +132,14 @@
|
|||||||
function fieldsToJustificatif() {
|
function fieldsToJustificatif() {
|
||||||
const field = document.querySelector('.justi-form')
|
const field = document.querySelector('.justi-form')
|
||||||
|
|
||||||
const date_debut = field.querySelector('#justi_date_debut').value;
|
const { deb, fin } = getDates()
|
||||||
const date_fin = field.querySelector('#justi_date_fin').value;
|
|
||||||
const etat = field.querySelector('#justi_etat').value;
|
const etat = field.querySelector('#justi_etat').value;
|
||||||
const raison = field.querySelector('#justi_raison').value;
|
const raison = field.querySelector('#justi_raison').value;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
date_debut: date_debut,
|
date_debut: deb,
|
||||||
date_fin: date_fin,
|
date_fin: fin,
|
||||||
etat: etat,
|
etat: etat,
|
||||||
raison: raison,
|
raison: raison,
|
||||||
}
|
}
|
||||||
@ -218,11 +218,43 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dayOnly() {
|
||||||
|
|
||||||
|
if (document.getElementById('justi_journee').checked) {
|
||||||
|
document.getElementById("date_fin").style.display = "none";
|
||||||
|
document.getElementById("justi_date_debut").type = "date"
|
||||||
|
} else {
|
||||||
|
document.getElementById("date_fin").style.display = "block";
|
||||||
|
document.getElementById("justi_date_debut").type = "datetime-local"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDates() {
|
||||||
|
if (document.getElementById('justi_journee').checked) {
|
||||||
|
const date_str = document.getElementById("justi_date_debut").value
|
||||||
|
|
||||||
|
return {
|
||||||
|
"deb": `${date_str}T${assi_morning}`,
|
||||||
|
"fin": `${date_str}T${assi_evening}`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"deb": document.getElementById("justi_date_debut").value,
|
||||||
|
"fin": document.getElementById("justi_date_fin").value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const etudid = {{ sco.etud.id }};
|
const etudid = {{ sco.etud.id }};
|
||||||
|
|
||||||
|
const assi_limit_annee = "{{ assi_limit_annee }}" == "True" ? true : false;
|
||||||
|
const assi_morning = '{{assi_morning}}';
|
||||||
|
const assi_evening = '{{assi_evening}}';
|
||||||
|
|
||||||
window.onload = () => {
|
window.onload = () => {
|
||||||
loadAll();
|
loadAll();
|
||||||
|
document.getElementById('justi_journee').addEventListener('click', () => { dayOnly() });
|
||||||
|
dayOnly()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock pageContent %}
|
{% endblock pageContent %}
|
@ -29,6 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
function loadAll() {
|
function loadAll() {
|
||||||
generate(defAnnee)
|
generate(defAnnee)
|
||||||
}
|
}
|
||||||
@ -57,7 +58,7 @@
|
|||||||
}
|
}
|
||||||
bornes = {
|
bornes = {
|
||||||
deb: `${annee}-09-01T00:00`,
|
deb: `${annee}-09-01T00:00`,
|
||||||
fin: `${annee + 1}-06-30T23:59`
|
fin: `${annee + 1}-08-31T23:59`
|
||||||
}
|
}
|
||||||
|
|
||||||
defAnnee = annee;
|
defAnnee = annee;
|
||||||
@ -75,10 +76,14 @@
|
|||||||
let defAnnee = {{ annee }};
|
let defAnnee = {{ annee }};
|
||||||
let bornes = {
|
let bornes = {
|
||||||
deb: `${defAnnee}-09-01T00:00`,
|
deb: `${defAnnee}-09-01T00:00`,
|
||||||
fin: `${defAnnee + 1}-06-30T23:59`
|
fin: `${defAnnee + 1}-08-31T23:59`
|
||||||
}
|
}
|
||||||
const dept_id = {{ dept_id }};
|
const dept_id = {{ dept_id }};
|
||||||
|
|
||||||
|
let annees = {{ annees | safe}}
|
||||||
|
|
||||||
|
annees = annees.filter((x, i) => annees.indexOf(x) === i)
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
|
|
||||||
filterJustificatifs = {
|
filterJustificatifs = {
|
||||||
@ -99,15 +104,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const select = document.querySelector('#annee');
|
const select = document.querySelector('#annee');
|
||||||
for (let i = defAnnee + 1; i > defAnnee - 6; i--) {
|
|
||||||
|
annees.forEach((a) => {
|
||||||
const opt = document.createElement("option");
|
const opt = document.createElement("option");
|
||||||
opt.value = i + "",
|
opt.value = a + "",
|
||||||
opt.textContent = i + "";
|
opt.textContent = `${a} - ${a + 1}`;
|
||||||
if (i === defAnnee) {
|
if (a === defAnnee) {
|
||||||
opt.selected = true;
|
opt.selected = true;
|
||||||
}
|
}
|
||||||
select.appendChild(opt)
|
select.appendChild(opt)
|
||||||
}
|
})
|
||||||
setterAnnee(defAnnee)
|
setterAnnee(defAnnee)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -266,6 +266,9 @@
|
|||||||
const assi_date_debut = "{{date_debut}}";
|
const assi_date_debut = "{{date_debut}}";
|
||||||
const assi_date_fin = "{{date_fin}}";
|
const assi_date_fin = "{{date_fin}}";
|
||||||
|
|
||||||
|
const assi_limit_annee = "{{ assi_limit_annee }}" == "True" ? true : false;
|
||||||
|
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
filterAssiduites = {
|
filterAssiduites = {
|
||||||
"columns": [
|
"columns": [
|
||||||
|
@ -354,5 +354,7 @@
|
|||||||
setterAnnee(defAnnee)
|
setterAnnee(defAnnee)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function isCalendrier() { return true }
|
||||||
</script>
|
</script>
|
||||||
{% endblock pageContent %}
|
{% endblock pageContent %}
|
@ -48,8 +48,43 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
const etudid = {{ sco.etud.id }}
|
const etudid = {{ sco.etud.id }}
|
||||||
|
|
||||||
|
const assiduite_unique_id = {{ assi_id }};
|
||||||
|
|
||||||
|
const assi_limit_annee = "{{ assi_limit_annee }}" == "True" ? true : false;
|
||||||
|
|
||||||
|
|
||||||
|
function wayForFilter() {
|
||||||
|
if (typeof assiduites[etudid] !== "undefined") {
|
||||||
|
console.log("Done")
|
||||||
|
let assiduite = assiduites[etudid].filter((a) => { return a.assiduite_id == assiduite_unique_id });
|
||||||
|
|
||||||
|
if (assiduite) {
|
||||||
|
assiduite = assiduite[0]
|
||||||
|
filterAssiduites["filters"] = {
|
||||||
|
"obj_id": [
|
||||||
|
assiduite.assiduite_id,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const obj_ids = assiduite.justificatifs ? assiduite.justificatifs.map((j) => { return j.justif_id }) : []
|
||||||
|
filterJustificatifs["filters"] = {
|
||||||
|
"obj_id": obj_ids
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAll();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setTimeout(wayForFilter, 250)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.onload = () => {
|
window.onload = () => {
|
||||||
loadAll();
|
loadAll();
|
||||||
|
|
||||||
|
if (assiduite_unique_id != -1) {
|
||||||
|
wayForFilter()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
@ -71,6 +71,11 @@
|
|||||||
updateSelectedSelect(getCurrentAssiduiteModuleImplId());
|
updateSelectedSelect(getCurrentAssiduiteModuleImplId());
|
||||||
updateJustifyBtn();
|
updateJustifyBtn();
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
if (isCalendrier()) {
|
||||||
|
window.location = `ListeAssiduitesEtud?etudid=${etudid}&assiduite_id=${assiduité.assiduite_id}`
|
||||||
|
}
|
||||||
|
} catch { }
|
||||||
});
|
});
|
||||||
//ajouter affichage assiduites on over
|
//ajouter affichage assiduites on over
|
||||||
setupAssiduiteBuble(block, assiduité);
|
setupAssiduiteBuble(block, assiduité);
|
||||||
|
@ -147,7 +147,7 @@
|
|||||||
<span class="obj-content">${etat}</span>
|
<span class="obj-content">${etat}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="user" class="obj-part">
|
<div id="user" class="obj-part">
|
||||||
<span class="obj-title">Créer par</span>
|
<span class="obj-title">Créée par</span>
|
||||||
<span class="obj-content">${user}</span>
|
<span class="obj-content">${user}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -239,7 +239,7 @@
|
|||||||
edit = setModuleImplId(edit, module);
|
edit = setModuleImplId(edit, module);
|
||||||
|
|
||||||
fullEditAssiduites(data.assiduite_id, edit, () => {
|
fullEditAssiduites(data.assiduite_id, edit, () => {
|
||||||
try { getAllAssiduitesFromEtud(etudid, assiduiteCallBack) } catch (_) { }
|
loadAll();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
document.addEventListener("click", () => {
|
document.addEventListener("click", () => {
|
||||||
contextMenu.style.display = "none";
|
contextMenu.style.display = "none";
|
||||||
|
if (contextMenu.childElementCount > 3) {
|
||||||
|
contextMenu.removeChild(contextMenu.lastElementChild)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
editOption.addEventListener("click", () => {
|
editOption.addEventListener("click", () => {
|
||||||
@ -94,6 +97,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (k == "obj_id") {
|
||||||
|
const obj_id = el.assiduite_id || el.justif_id;
|
||||||
|
return f.obj_id.includes(obj_id)
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -150,7 +158,7 @@
|
|||||||
paginationContainerAssiduites.querySelector('.pagination_moins').addEventListener('click', () => {
|
paginationContainerAssiduites.querySelector('.pagination_moins').addEventListener('click', () => {
|
||||||
if (currentPageAssiduites > 1) {
|
if (currentPageAssiduites > 1) {
|
||||||
currentPageAssiduites--;
|
currentPageAssiduites--;
|
||||||
paginationContainerAssiduites.querySelector('#paginationAssi').value = currentPageAssiduites
|
paginationContainerAssiduites.querySelector('#paginationAssi').value = currentPageAssiduites + ""
|
||||||
assiduiteCallBack(array);
|
assiduiteCallBack(array);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -159,7 +167,7 @@
|
|||||||
paginationContainerAssiduites.querySelector('.pagination_plus').addEventListener('click', () => {
|
paginationContainerAssiduites.querySelector('.pagination_plus').addEventListener('click', () => {
|
||||||
if (currentPageAssiduites < totalPages) {
|
if (currentPageAssiduites < totalPages) {
|
||||||
currentPageAssiduites++;
|
currentPageAssiduites++;
|
||||||
paginationContainerAssiduites.querySelector('#paginationAssi').value = currentPageAssiduites
|
paginationContainerAssiduites.querySelector('#paginationAssi').value = currentPageAssiduites + ""
|
||||||
assiduiteCallBack(array);
|
assiduiteCallBack(array);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -199,8 +207,12 @@
|
|||||||
|
|
||||||
if (assi) {
|
if (assi) {
|
||||||
paginationContainerAssiduites.querySelector('#paginationAssi').appendChild(paginationButton)
|
paginationContainerAssiduites.querySelector('#paginationAssi').appendChild(paginationButton)
|
||||||
|
if (i == currentPageAssiduites)
|
||||||
|
paginationContainerAssiduites.querySelector('#paginationAssi').value = i + "";
|
||||||
} else {
|
} else {
|
||||||
paginationContainerJustificatifs.querySelector('#paginationJusti').appendChild(paginationButton)
|
paginationContainerJustificatifs.querySelector('#paginationJusti').appendChild(paginationButton)
|
||||||
|
if (i == currentPageJustificatifs)
|
||||||
|
paginationContainerJustificatifs.querySelector('#paginationJusti').value = i + "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateActivePaginationButton(assi);
|
updateActivePaginationButton(assi);
|
||||||
@ -230,8 +242,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadAll() {
|
function loadAll() {
|
||||||
try { getAllAssiduitesFromEtud(etudid, assiduiteCallBack) } catch (_) { }
|
try { getAllAssiduitesFromEtud(etudid, assiduiteCallBack, true, true, assi_limit_annee) } catch (_) { }
|
||||||
try { getAllJustificatifsFromEtud(etudid, justificatifCallBack) } catch (_) { }
|
try { getAllJustificatifsFromEtud(etudid, justificatifCallBack, true, assi_limit_annee) } catch (_) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
function order(keyword, callback = () => { }, el, assi = true) {
|
function order(keyword, callback = () => { }, el, assi = true) {
|
||||||
@ -641,6 +653,27 @@
|
|||||||
contextMenu.style.top = `${e.clientY - contextMenu.offsetHeight}px`;
|
contextMenu.style.top = `${e.clientY - contextMenu.offsetHeight}px`;
|
||||||
contextMenu.style.left = `${e.clientX}px`;
|
contextMenu.style.left = `${e.clientX}px`;
|
||||||
contextMenu.style.display = "block";
|
contextMenu.style.display = "block";
|
||||||
|
if (contextMenu.childElementCount > 3) {
|
||||||
|
contextMenu.removeChild(contextMenu.lastElementChild)
|
||||||
|
}
|
||||||
|
if (selectedRow.getAttribute('type') == "assiduite") {
|
||||||
|
|
||||||
|
const li = document.createElement('li')
|
||||||
|
li.textContent = "Justifier"
|
||||||
|
|
||||||
|
li.addEventListener('click', () => {
|
||||||
|
let obj_id = selectedRow.getAttribute('obj_id');
|
||||||
|
assiduite = Object.values(assiduites).flat().filter((a) => { return a.assiduite_id == obj_id })
|
||||||
|
console.log(assiduite[0])
|
||||||
|
if (assiduite && !assiduite[0].est_just && assiduite[0].etat != "PRESENT") {
|
||||||
|
fastJustify(assiduite[0])
|
||||||
|
} else {
|
||||||
|
openAlertModal("Erreur", document.createTextNode("L'assiduité est déjà justifiée ou ne peut pas l'être."))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
contextMenu.appendChild(li)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -169,7 +169,7 @@
|
|||||||
<span class="obj-content">${etat}</span>
|
<span class="obj-content">${etat}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="user" class="obj-part">
|
<div id="user" class="obj-part">
|
||||||
<span class="obj-title">Créer par</span>
|
<span class="obj-title">Créé par</span>
|
||||||
<span class="obj-content">${user}</span>
|
<span class="obj-content">${user}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
const period_default = {{ periode_defaut }};
|
const period_default = {{ periode_defaut }};
|
||||||
|
|
||||||
|
let handleMoving = false;
|
||||||
|
|
||||||
function createTicks() {
|
function createTicks() {
|
||||||
let i = t_start;
|
let i = t_start;
|
||||||
|
|
||||||
@ -87,42 +89,21 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupTimeLine(callback) {
|
function timelineMainEvent(event, callback) {
|
||||||
const func_call = callback ? callback : () => { };
|
const func_call = callback ? callback : () => { };
|
||||||
timelineContainer.addEventListener("mousedown", (event) => {
|
|
||||||
const startX = event.clientX;
|
|
||||||
|
|
||||||
if (event.target === periodTimeLine) {
|
const startX = (event.clientX || event.changedTouches[0].clientX);
|
||||||
const startLeft = parseFloat(periodTimeLine.style.left);
|
|
||||||
|
|
||||||
const onMouseMove = (moveEvent) => {
|
if (event.target.classList.contains("period-handle")) {
|
||||||
const deltaX = moveEvent.clientX - startX;
|
|
||||||
const containerWidth = timelineContainer.clientWidth;
|
|
||||||
const newLeft = startLeft + (deltaX / containerWidth) * 100;
|
|
||||||
|
|
||||||
adjustPeriodPosition(newLeft, parseFloat(periodTimeLine.style.width));
|
|
||||||
|
|
||||||
updatePeriodTimeLabel();
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("mousemove", onMouseMove);
|
|
||||||
document.addEventListener(
|
|
||||||
"mouseup",
|
|
||||||
() => {
|
|
||||||
generateAllEtudRow();
|
|
||||||
snapHandlesToQuarters();
|
|
||||||
document.removeEventListener("mousemove", onMouseMove);
|
|
||||||
func_call();
|
|
||||||
},
|
|
||||||
{ once: true }
|
|
||||||
);
|
|
||||||
} else if (event.target.classList.contains("period-handle")) {
|
|
||||||
const startWidth = parseFloat(periodTimeLine.style.width);
|
const startWidth = parseFloat(periodTimeLine.style.width);
|
||||||
const startLeft = parseFloat(periodTimeLine.style.left);
|
const startLeft = parseFloat(periodTimeLine.style.left);
|
||||||
const isLeftHandle = event.target.classList.contains("left");
|
const isLeftHandle = event.target.classList.contains("left");
|
||||||
|
handleMoving = true
|
||||||
const onMouseMove = (moveEvent) => {
|
const onMouseMove = (moveEvent) => {
|
||||||
const deltaX = moveEvent.clientX - startX;
|
|
||||||
|
if (!handleMoving) return;
|
||||||
|
|
||||||
|
const deltaX = (moveEvent.clientX || moveEvent.changedTouches[0].clientX) - startX;
|
||||||
const containerWidth = timelineContainer.clientWidth;
|
const containerWidth = timelineContainer.clientWidth;
|
||||||
const newWidth =
|
const newWidth =
|
||||||
startWidth + ((isLeftHandle ? -deltaX : deltaX) / containerWidth) * 100;
|
startWidth + ((isLeftHandle ? -deltaX : deltaX) / containerWidth) * 100;
|
||||||
@ -136,23 +117,64 @@
|
|||||||
|
|
||||||
updatePeriodTimeLabel();
|
updatePeriodTimeLabel();
|
||||||
};
|
};
|
||||||
|
const mouseUp = () => {
|
||||||
document.addEventListener("mousemove", onMouseMove);
|
|
||||||
document.addEventListener(
|
|
||||||
"mouseup",
|
|
||||||
() => {
|
|
||||||
snapHandlesToQuarters();
|
snapHandlesToQuarters();
|
||||||
generateAllEtudRow();
|
generateAllEtudRow();
|
||||||
|
|
||||||
document.removeEventListener("mousemove", onMouseMove);
|
timelineContainer.removeEventListener("mousemove", onMouseMove);
|
||||||
|
handleMoving = false;
|
||||||
func_call();
|
func_call();
|
||||||
|
|
||||||
},
|
}
|
||||||
|
timelineContainer.addEventListener("mousemove", onMouseMove);
|
||||||
|
timelineContainer.addEventListener("touchmove", onMouseMove);
|
||||||
|
document.addEventListener(
|
||||||
|
"mouseup",
|
||||||
|
mouseUp,
|
||||||
|
);
|
||||||
|
document.addEventListener(
|
||||||
|
"touchend",
|
||||||
|
mouseUp,
|
||||||
|
);
|
||||||
|
} else if (event.target === periodTimeLine) {
|
||||||
|
|
||||||
|
const startLeft = parseFloat(periodTimeLine.style.left);
|
||||||
|
|
||||||
|
const onMouseMove = (moveEvent) => {
|
||||||
|
console.warn("move Period")
|
||||||
|
if (handleMoving) return;
|
||||||
|
const deltaX = (moveEvent.clientX || moveEvent.changedTouches[0].clientX) - startX;
|
||||||
|
const containerWidth = timelineContainer.clientWidth;
|
||||||
|
const newLeft = startLeft + (deltaX / containerWidth) * 100;
|
||||||
|
|
||||||
|
adjustPeriodPosition(newLeft, parseFloat(periodTimeLine.style.width));
|
||||||
|
|
||||||
|
updatePeriodTimeLabel();
|
||||||
|
};
|
||||||
|
const mouseUp = () => {
|
||||||
|
generateAllEtudRow();
|
||||||
|
snapHandlesToQuarters();
|
||||||
|
timelineContainer.removeEventListener("mousemove", onMouseMove);
|
||||||
|
func_call();
|
||||||
|
}
|
||||||
|
timelineContainer.addEventListener("mousemove", onMouseMove);
|
||||||
|
timelineContainer.addEventListener("touchmove", onMouseMove);
|
||||||
|
document.addEventListener(
|
||||||
|
"mouseup",
|
||||||
|
mouseUp,
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
document.addEventListener(
|
||||||
|
"touchend",
|
||||||
|
mouseUp,
|
||||||
{ once: true }
|
{ once: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
function setupTimeLine(callback) {
|
||||||
|
timelineContainer.addEventListener("mousedown", (e) => { timelineMainEvent(e, callback) });
|
||||||
|
timelineContainer.addEventListener("touchstart", (e) => { timelineMainEvent(e, callback) });
|
||||||
}
|
}
|
||||||
|
|
||||||
function adjustPeriodPosition(newLeft, newWidth) {
|
function adjustPeriodPosition(newLeft, newWidth) {
|
||||||
|
@ -162,24 +162,35 @@ def index_html():
|
|||||||
"""<p class="help">Pour signaler, annuler ou justifier une assiduité pour un seul étudiant,
|
"""<p class="help">Pour signaler, annuler ou justifier une assiduité pour un seul étudiant,
|
||||||
choisissez d'abord le concerné:</p>"""
|
choisissez d'abord le concerné:</p>"""
|
||||||
)
|
)
|
||||||
H.append(sco_find_etud.form_search_etud())
|
H.append(sco_find_etud.form_search_etud(dest_url="assiduites.bilan_etud"))
|
||||||
# if current_user.has_permission(
|
if current_user.has_permission(
|
||||||
# Permission.ScoAbsChange
|
Permission.ScoAbsChange
|
||||||
# ) and sco_preferences.get_preference("handle_billets_abs"):
|
) and sco_preferences.get_preference("handle_billets_abs"):
|
||||||
# H.append(
|
H.append(
|
||||||
# f"""
|
f"""
|
||||||
# <h2 style="margin-top: 30px;">Billets d'absence</h2>
|
<h2 style="margin-top: 30px;">Billets d'absence</h2>
|
||||||
# <ul><li><a href="{url_for("absences.list_billets", scodoc_dept=g.scodoc_dept)
|
<ul><li><a href="{url_for("absences.list_billets", scodoc_dept=g.scodoc_dept)
|
||||||
# }">Traitement des billets d'absence en attente</a>
|
}">Traitement des billets d'absence en attente</a>
|
||||||
# </li></ul>
|
</li></ul>
|
||||||
# """
|
"""
|
||||||
# )
|
)
|
||||||
|
dept: Departement = Departement.query.filter_by(id=g.scodoc_dept_id).first()
|
||||||
|
annees: list[int] = sorted(
|
||||||
|
[f.date_debut.year for f in dept.formsemestres],
|
||||||
|
reverse=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
annees_str: str = "["
|
||||||
|
for ann in annees:
|
||||||
|
annees_str += f"{ann},"
|
||||||
|
annees_str += "]"
|
||||||
|
|
||||||
H.append(
|
H.append(
|
||||||
render_template(
|
render_template(
|
||||||
"assiduites/pages/bilan_dept.j2",
|
"assiduites/pages/bilan_dept.j2",
|
||||||
dept_id=g.scodoc_dept_id,
|
dept_id=g.scodoc_dept_id,
|
||||||
annee=scu.annee_scolaire(),
|
annee=scu.annee_scolaire(),
|
||||||
|
annees=annees_str,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
H.append(html_sco_header.sco_footer())
|
H.append(html_sco_header.sco_footer())
|
||||||
@ -299,6 +310,8 @@ def liste_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")
|
||||||
|
|
||||||
|
assiduite_id: int = request.args.get("assiduite_id", -1)
|
||||||
|
|
||||||
header: str = html_sco_header.sco_header(
|
header: str = html_sco_header.sco_header(
|
||||||
page_title="Liste des assiduités",
|
page_title="Liste des assiduités",
|
||||||
init_qtip=True,
|
init_qtip=True,
|
||||||
@ -319,6 +332,11 @@ def liste_assiduites_etud():
|
|||||||
"assiduites/pages/liste_assiduites.j2",
|
"assiduites/pages/liste_assiduites.j2",
|
||||||
sco=ScoData(etud),
|
sco=ScoData(etud),
|
||||||
date=datetime.date.today().isoformat(),
|
date=datetime.date.today().isoformat(),
|
||||||
|
assi_id=assiduite_id,
|
||||||
|
assi_limit_annee=sco_preferences.get_preference(
|
||||||
|
"assi_limit_annee",
|
||||||
|
dept_id=g.scodoc_dept_id,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
).build()
|
).build()
|
||||||
|
|
||||||
@ -371,6 +389,10 @@ def bilan_etud():
|
|||||||
date_fin=date_fin,
|
date_fin=date_fin,
|
||||||
assi_metric=assi_metric,
|
assi_metric=assi_metric,
|
||||||
assi_seuil=_get_seuil(),
|
assi_seuil=_get_seuil(),
|
||||||
|
assi_limit_annee=sco_preferences.get_preference(
|
||||||
|
"assi_limit_annee",
|
||||||
|
dept_id=g.scodoc_dept_id,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
).build()
|
).build()
|
||||||
|
|
||||||
@ -412,6 +434,12 @@ def ajout_justificatif_etud():
|
|||||||
render_template(
|
render_template(
|
||||||
"assiduites/pages/ajout_justificatif.j2",
|
"assiduites/pages/ajout_justificatif.j2",
|
||||||
sco=ScoData(etud),
|
sco=ScoData(etud),
|
||||||
|
assi_limit_annee=sco_preferences.get_preference(
|
||||||
|
"assi_limit_annee",
|
||||||
|
dept_id=g.scodoc_dept_id,
|
||||||
|
),
|
||||||
|
assi_morning=ScoDocSiteConfig.get("assi_morning_time", "08:00"),
|
||||||
|
assi_evening=ScoDocSiteConfig.get("assi_evening_time", "18:00"),
|
||||||
),
|
),
|
||||||
).build()
|
).build()
|
||||||
|
|
||||||
|
@ -157,7 +157,6 @@ def test_general(test_client):
|
|||||||
editer_supprimer_justificatif(etuds[0])
|
editer_supprimer_justificatif(etuds[0])
|
||||||
|
|
||||||
|
|
||||||
# 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)
|
||||||
|
Loading…
Reference in New Issue
Block a user