forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -18,7 +18,7 @@ from app.api import api_bp as bp
|
|||||||
from app.api import api_web_bp
|
from app.api import api_web_bp
|
||||||
from app.api import get_model_api_object
|
from app.api import get_model_api_object
|
||||||
from app.decorators import permission_required, scodoc
|
from app.decorators import permission_required, scodoc
|
||||||
from app.models import Identite, Justificatif
|
from app.models import Identite, Justificatif, Departement
|
||||||
from app.models.assiduites import compute_assiduites_justified
|
from app.models.assiduites import compute_assiduites_justified
|
||||||
from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
|
from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
@ -105,6 +105,31 @@ def justificatifs(etudid: int = None, with_query: bool = False):
|
|||||||
return data_set
|
return data_set
|
||||||
|
|
||||||
|
|
||||||
|
@api_web_bp.route("/justificatifs/dept/<int:dept_id>", defaults={"with_query": False})
|
||||||
|
@api_web_bp.route(
|
||||||
|
"/justificatifs/dept/<int:dept_id>/query", defaults={"with_query": True}
|
||||||
|
)
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@as_json
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def justificatifs_dept(dept_id: int = None, with_query : bool = False):
|
||||||
|
""" """
|
||||||
|
dept = Departement.query.get_or_404(dept_id)
|
||||||
|
etuds = [etud.id for etud in dept.etudiants]
|
||||||
|
|
||||||
|
justificatifs_query = Justificatif.query.filter(Justificatif.etudid.in_(etuds))
|
||||||
|
|
||||||
|
if with_query:
|
||||||
|
justificatifs_query = _filter_manager(request, justificatifs_query)
|
||||||
|
data_set: list[dict] = []
|
||||||
|
for just in justificatifs_query.all():
|
||||||
|
data = just.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"])
|
||||||
@scodoc
|
@scodoc
|
||||||
|
@ -54,7 +54,7 @@ def sidebar_common():
|
|||||||
<h2 class="insidebar">Scolarité</h2>
|
<h2 class="insidebar">Scolarité</h2>
|
||||||
<a href="{scu.ScoURL()}" class="sidebar">Semestres</a> <br>
|
<a href="{scu.ScoURL()}" class="sidebar">Semestres</a> <br>
|
||||||
<a href="{scu.NotesURL()}" class="sidebar">Programmes</a> <br>
|
<a href="{scu.NotesURL()}" class="sidebar">Programmes</a> <br>
|
||||||
<a href="{scu.AbsencesURL()}" class="sidebar">Absences</a> <br>
|
<a href="{scu.AssiduitesURL()}" class="sidebar">Assiduités</a> <br>
|
||||||
"""
|
"""
|
||||||
]
|
]
|
||||||
if current_user.has_permission(
|
if current_user.has_permission(
|
||||||
@ -138,6 +138,7 @@ def sidebar(etudid: int = None):
|
|||||||
f"""
|
f"""
|
||||||
<li><a href="{ url_for('assiduites.calendrier_etud', scodoc_dept=g.scodoc_dept, etudid=etudid) }">Calendrier</a></li>
|
<li><a href="{ url_for('assiduites.calendrier_etud', scodoc_dept=g.scodoc_dept, etudid=etudid) }">Calendrier</a></li>
|
||||||
<li><a href="{ url_for('assiduites.liste_assiduites_etud', scodoc_dept=g.scodoc_dept, etudid=etudid) }">Liste</a></li>
|
<li><a href="{ url_for('assiduites.liste_assiduites_etud', scodoc_dept=g.scodoc_dept, etudid=etudid) }">Liste</a></li>
|
||||||
|
<li><a href="{ url_for('assiduites.bilan_etud', scodoc_dept=g.scodoc_dept, etudid=etudid) }">Bilan</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@ -213,13 +213,14 @@ def formsemestre_status_menubar(formsemestre: FormSemestre) -> str:
|
|||||||
"enabled": True,
|
"enabled": True,
|
||||||
"helpmsg": "",
|
"helpmsg": "",
|
||||||
},
|
},
|
||||||
{
|
# TODO: Mettre à jour avec module Assiduités
|
||||||
"title": "Vérifier absences aux évaluations",
|
# {
|
||||||
"endpoint": "notes.formsemestre_check_absences_html",
|
# "title": "Vérifier absences aux évaluations",
|
||||||
"args": {"formsemestre_id": formsemestre_id},
|
# "endpoint": "notes.formsemestre_check_absences_html",
|
||||||
"enabled": True,
|
# "args": {"formsemestre_id": formsemestre_id},
|
||||||
"helpmsg": "",
|
# "enabled": True,
|
||||||
},
|
# "helpmsg": "",
|
||||||
|
# },
|
||||||
{
|
{
|
||||||
"title": "Lister tous les enseignants",
|
"title": "Lister tous les enseignants",
|
||||||
"endpoint": "notes.formsemestre_enseignants_list",
|
"endpoint": "notes.formsemestre_enseignants_list",
|
||||||
|
@ -138,7 +138,7 @@ def moduleimpl_evaluation_menu(evaluation_id, nbnotes=0) -> str:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Absences ce jour",
|
"title": "Absences ce jour",
|
||||||
"endpoint": "absences.EtatAbsencesDate",
|
"endpoint": "assiduites.get_etat_abs_date",
|
||||||
"args": {
|
"args": {
|
||||||
"group_ids": group_id,
|
"group_ids": group_id,
|
||||||
"desc": E["description"],
|
"desc": E["description"],
|
||||||
|
@ -661,7 +661,19 @@ class BasePreferences(object):
|
|||||||
"labels": ["1/2 J.", "J.", "H."],
|
"labels": ["1/2 J.", "J.", "H."],
|
||||||
"allowed_values": ["1/2 J.", "J.", "H."],
|
"allowed_values": ["1/2 J.", "J.", "H."],
|
||||||
"title": "Métrique de l'assiduité",
|
"title": "Métrique de l'assiduité",
|
||||||
"explanation": "Unité affichée dans la fiche étudiante et le bilan\n(J. = journée, H. = heure)",
|
"explanation": "Unité utilisée dans la fiche étudiante, le bilan, et dans les calculs (J. = journée, H. = heure)",
|
||||||
|
"category": "assi",
|
||||||
|
"only_global": True,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"assi_seuil",
|
||||||
|
{
|
||||||
|
"initvalue": 3.0,
|
||||||
|
"size": 10,
|
||||||
|
"title": "Seuil d'alerte des absences",
|
||||||
|
"type": "float",
|
||||||
|
"explanation": "Nombres d'absences limite avant alerte dans le bilan (utilisation de l'unité métrique ↑ )",
|
||||||
"category": "assi",
|
"category": "assi",
|
||||||
"only_global": True,
|
"only_global": True,
|
||||||
},
|
},
|
||||||
|
@ -619,6 +619,13 @@ def AbsencesURL():
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def AssiduitesURL():
|
||||||
|
"""URL of Assiduités"""
|
||||||
|
return url_for("assiduites.index_html", scodoc_dept=g.scodoc_dept)[
|
||||||
|
: -len("/index_html")
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def UsersURL():
|
def UsersURL():
|
||||||
"""URL of Users
|
"""URL of Users
|
||||||
e.g. https://scodoc.xxx.fr/ScoDoc/DEPT/Scolarite/Users
|
e.g. https://scodoc.xxx.fr/ScoDoc/DEPT/Scolarite/Users
|
||||||
|
160
app/templates/assiduites/pages/bilan_dept.j2
Normal file
160
app/templates/assiduites/pages/bilan_dept.j2
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
{% include "assiduites/widgets/tableau_base.j2" %}
|
||||||
|
<section class="alerte invisible">
|
||||||
|
<p>Attention, cet étudiant a trop d'absences</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="nonvalide">
|
||||||
|
<!-- Tableaux des justificatifs à valider (attente / modifié ) -->
|
||||||
|
<h4>Justificatifs en attente (ou modifiés)</h4>
|
||||||
|
{% include "assiduites/widgets/tableau_justi.j2" %}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="annee">
|
||||||
|
<span>Année scolaire 2022-2023 Changer année: </span>
|
||||||
|
<select name="" id="annee" onchange="setterAnnee(this.value)">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="legende">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function loadAll() {
|
||||||
|
generate(defAnnee)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDeptJustificatifsFromPeriod(action) {
|
||||||
|
const path = getUrl() + `/api/justificatifs/dept/${dept_id}/query?date_debut=${bornes.deb}&date_fin=${bornes.fin}&etat=attente,modifie`
|
||||||
|
async_get(
|
||||||
|
path,
|
||||||
|
(data, status) => {
|
||||||
|
console.log(data);
|
||||||
|
justificatifCallBack(data);
|
||||||
|
|
||||||
|
},
|
||||||
|
(data, status) => {
|
||||||
|
console.error(data, status)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate(annee) {
|
||||||
|
|
||||||
|
if (annee < 1999 || annee > 2999) {
|
||||||
|
openAlertModal("Année impossible", document.createTextNode("L'année demandé n'existe pas."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bornes = {
|
||||||
|
deb: `${annee}-09-01T00:00`,
|
||||||
|
fin: `${annee + 1}-06-30T23:59`
|
||||||
|
}
|
||||||
|
|
||||||
|
defAnnee = annee;
|
||||||
|
|
||||||
|
getDeptJustificatifsFromPeriod()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function setterAnnee(annee) {
|
||||||
|
annee = parseInt(annee);
|
||||||
|
document.querySelector('.annee span').textContent = `Année scolaire ${annee}-${annee + 1} Changer année: `
|
||||||
|
generate(annee)
|
||||||
|
|
||||||
|
}
|
||||||
|
let defAnnee = {{ annee }};
|
||||||
|
let bornes = {
|
||||||
|
deb: `${defAnnee}-09-01T00:00`,
|
||||||
|
fin: `${defAnnee + 1}-06-30T23:59`
|
||||||
|
}
|
||||||
|
const dept_id = {{ dept_id }};
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
|
||||||
|
filterJustificatifs = {
|
||||||
|
"columns": [
|
||||||
|
"etudid",
|
||||||
|
"entry_date",
|
||||||
|
"date_debut",
|
||||||
|
"date_fin",
|
||||||
|
"etat",
|
||||||
|
"raison",
|
||||||
|
"fichier"
|
||||||
|
],
|
||||||
|
"filters": {
|
||||||
|
"etat": [
|
||||||
|
"attente",
|
||||||
|
"modifie"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const select = document.querySelector('#annee');
|
||||||
|
for (let i = defAnnee + 1; i > defAnnee - 6; i--) {
|
||||||
|
const opt = document.createElement("option");
|
||||||
|
opt.value = i + "",
|
||||||
|
opt.textContent = i + "";
|
||||||
|
if (i === defAnnee) {
|
||||||
|
opt.selected = true;
|
||||||
|
}
|
||||||
|
select.appendChild(opt)
|
||||||
|
}
|
||||||
|
setterAnnee(defAnnee)
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.stats-values-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
border: 1px solid #333;
|
||||||
|
padding: 5px 2px;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-values {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-values-item h5 {
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-values-part {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerte {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-radius: 7px;
|
||||||
|
|
||||||
|
background-color: crimson;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerte.invisible {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerte p {
|
||||||
|
font-size: larger;
|
||||||
|
color: whitesmoke;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.suppr {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
</style>
|
342
app/templates/assiduites/pages/bilan_etud.j2
Normal file
342
app/templates/assiduites/pages/bilan_etud.j2
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
{% block app_content %}
|
||||||
|
{% include "assiduites/widgets/tableau_base.j2" %}
|
||||||
|
<div class="pageContent">
|
||||||
|
|
||||||
|
<h2>Bilan de l'assiduité de <span class="rouge">{{sco.etud.nomprenom}}</span></h2>
|
||||||
|
|
||||||
|
<section class="alerte invisible">
|
||||||
|
<p>Attention, cet étudiant a trop d'absences</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="stats">
|
||||||
|
<!-- Statistiques d'assiduité (nb pres, nb retard, nb absence) + nb justifié -->
|
||||||
|
<h4>Statistiques d'assiduité</h4>
|
||||||
|
<div class="stats-inputs">
|
||||||
|
<label class="stats-label"> Date de début<input type="date" name="stats_date_debut" id="stats_date_debut"
|
||||||
|
value="{{date_debut}}"></label>
|
||||||
|
<label class="stats-label"> Date de fin<input type="date" name="stats_date_fin" id="stats_date_fin"
|
||||||
|
value="{{date_fin}}"></label>
|
||||||
|
<button onclick="stats()">Actualiser</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stats-values">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="nonvalide">
|
||||||
|
<!-- Tableaux des assiduités (retard/abs) non justifiées -->
|
||||||
|
<h4>Assiduités non justifiées (Uniquement les retards et les absences)</h4>
|
||||||
|
{% include "assiduites/widgets/tableau_assi.j2" %}
|
||||||
|
<!-- Tableaux des justificatifs à valider (attente / modifié ) -->
|
||||||
|
<h4>Justificatifs en attente (ou modifiés)</h4>
|
||||||
|
{% include "assiduites/widgets/tableau_justi.j2" %}
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="suppr">
|
||||||
|
<h4>Boutons de suppresions (toute suppression est définitive) </h4>
|
||||||
|
<button type="button" onclick="removeAllAssiduites()">Suppression des assiduités</button>
|
||||||
|
<button type="button" onclick="removeAllJustificatifs()">Suppression des justificatifs</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="legende">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock app_content %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function stats() {
|
||||||
|
const dd_val = document.getElementById('stats_date_debut').value;
|
||||||
|
const df_val = document.getElementById('stats_date_fin').value;
|
||||||
|
|
||||||
|
if (dd_val == "" || df_val == "") {
|
||||||
|
openAlertModal("Dates invalides", document.createTextNode('Les dates sélectionnées sont invalides'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const date_debut = new moment.tz(dd_val + "T00:00", TIMEZONE);
|
||||||
|
const date_fin = new moment.tz(df_val + "T23:59", TIMEZONE);
|
||||||
|
|
||||||
|
if (date_debut.valueOf() > date_fin.valueOf()) {
|
||||||
|
openAlertModal("Dates invalides", document.createTextNode('La date de début se situe après la date de fin.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
countAssiduites(date_debut.format(), date_fin.format())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAssiduitesCount(dateDeb, dateFin, query) {
|
||||||
|
const url_api = getUrl() + `/api/assiduites/${etudid}/count/query?date_debut=${dateDeb}&date_fin=${dateFin}&${query}`;
|
||||||
|
return $.ajax({
|
||||||
|
async: true,
|
||||||
|
type: "GET",
|
||||||
|
url: url_api,
|
||||||
|
success: (data, status) => {
|
||||||
|
if (status === "success") {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: () => { },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function countAssiduites(dateDeb, dateFin) {
|
||||||
|
$.when(
|
||||||
|
getAssiduitesCount(dateDeb, dateFin, `etat=present`),
|
||||||
|
getAssiduitesCount(dateDeb, dateFin, `etat=present&est_just=v`),
|
||||||
|
getAssiduitesCount(dateDeb, dateFin, `etat=retard`),
|
||||||
|
getAssiduitesCount(dateDeb, dateFin, `etat=retard&est_just=v`),
|
||||||
|
getAssiduitesCount(dateDeb, dateFin, `etat=absent`),
|
||||||
|
getAssiduitesCount(dateDeb, dateFin, `etat=absent&est_just=v`),
|
||||||
|
).then(
|
||||||
|
(pt, pj, rt, rj, at, aj) => {
|
||||||
|
const counter = {
|
||||||
|
"present": {
|
||||||
|
"total": pt[0],
|
||||||
|
"justi": pj[0],
|
||||||
|
},
|
||||||
|
"retard": {
|
||||||
|
"total": rt[0],
|
||||||
|
"justi": rj[0],
|
||||||
|
},
|
||||||
|
"absent": {
|
||||||
|
"total": at[0],
|
||||||
|
"justi": aj[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const values = document.querySelector('.stats-values');
|
||||||
|
values.innerHTML = "";
|
||||||
|
|
||||||
|
Object.keys(counter).forEach((key) => {
|
||||||
|
const item = document.createElement('div');
|
||||||
|
item.classList.add('stats-values-item');
|
||||||
|
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.classList.add('stats-values-part');
|
||||||
|
|
||||||
|
const heure = document.createElement('span');
|
||||||
|
heure.textContent = `${counter[key].total.heure} heure(s) dont ${counter[key].justi.heure} justifiées`;
|
||||||
|
|
||||||
|
const demi = document.createElement('span');
|
||||||
|
demi.textContent = `${counter[key].total.demi} demi-journée(s) dont ${counter[key].justi.demi} justifiées`;
|
||||||
|
|
||||||
|
const jour = document.createElement('span');
|
||||||
|
jour.textContent = `${counter[key].total.journee} journée(s) dont ${counter[key].justi.journee} justifiées`;
|
||||||
|
|
||||||
|
div.append(jour, demi, heure);
|
||||||
|
|
||||||
|
const title = document.createElement('h5');
|
||||||
|
title.textContent = key.capitalize();
|
||||||
|
|
||||||
|
item.append(title, div)
|
||||||
|
|
||||||
|
values.appendChild(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
const nbAbs = counter.absent.total[assi_metric] - counter.absent.justi[assi_metric];
|
||||||
|
if (nbAbs > assi_seuil) {
|
||||||
|
document.querySelector('.alerte').classList.remove('invisible');
|
||||||
|
document.querySelector('.alerte p').textContent = `Attention, cet étudiant a trop d'absences ${nbAbs} / ${assi_seuil} (${metriques[assi_metric]})`
|
||||||
|
} else {
|
||||||
|
document.querySelector('.alerte').classList.add('invisible');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeAllAssiduites() {
|
||||||
|
|
||||||
|
openPromptModal(
|
||||||
|
"Suppression des assiduités",
|
||||||
|
document.createTextNode(
|
||||||
|
'Souhaitez vous réelement supprimer toutes les assiduités de cet étudiant ? Cette supression est irréversible.')
|
||||||
|
,
|
||||||
|
() => {
|
||||||
|
getAllAssiduitesFromEtud(etudid, (data) => {
|
||||||
|
const toRemove = data.map((a) => a.assiduite_id);
|
||||||
|
console.log(toRemove)
|
||||||
|
deleteAssiduites(toRemove);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
function removeAllJustificatifs() {
|
||||||
|
openPromptModal(
|
||||||
|
"Suppression des justificatifs",
|
||||||
|
document.createTextNode(
|
||||||
|
'Souhaitez vous réelement supprimer tous les justificatifs de cet étudiant ? Cette supression est irréversible.')
|
||||||
|
,
|
||||||
|
() => {
|
||||||
|
getAllJustificatifsFromEtud(etudid, (data) => {
|
||||||
|
const toRemove = data.map((a) => a.justif_id);
|
||||||
|
|
||||||
|
deleteJustificatifs(toRemove);
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Suppression des assiduties
|
||||||
|
*/
|
||||||
|
function deleteAssiduites(assi) {
|
||||||
|
const path = getUrl() + `/api/assiduite/delete`;
|
||||||
|
async_post(
|
||||||
|
path,
|
||||||
|
assi,
|
||||||
|
(data, status) => {
|
||||||
|
//success
|
||||||
|
if (data.success.length > 0) {
|
||||||
|
}
|
||||||
|
location.reload();
|
||||||
|
},
|
||||||
|
(data, status) => {
|
||||||
|
//error
|
||||||
|
console.error(data, status);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Suppression des justificatifs
|
||||||
|
*/
|
||||||
|
function deleteJustificatifs(justis) {
|
||||||
|
const path = getUrl() + `/api/justificatif/delete`;
|
||||||
|
async_post(
|
||||||
|
path,
|
||||||
|
justis,
|
||||||
|
(data, status) => {
|
||||||
|
//success
|
||||||
|
location.reload();
|
||||||
|
},
|
||||||
|
(data, status) => {
|
||||||
|
//error
|
||||||
|
console.error(data, status);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const metriques = {
|
||||||
|
"heure": "H.",
|
||||||
|
"demi": "1/2 J.",
|
||||||
|
"journee": "J."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const etudid = {{ sco.etud.id }};
|
||||||
|
const assi_metric = "{{ assi_metric | safe }}";
|
||||||
|
const assi_seuil = {{ assi_seuil }};
|
||||||
|
|
||||||
|
const assi_date_debut = "{{date_debut}}";
|
||||||
|
const assi_date_fin = "{{date_fin}}";
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
filterAssiduites = {
|
||||||
|
"columns": [
|
||||||
|
"entry_date",
|
||||||
|
"date_debut",
|
||||||
|
"date_fin",
|
||||||
|
"etat",
|
||||||
|
"moduleimpl_id",
|
||||||
|
"est_just"
|
||||||
|
],
|
||||||
|
"filters": {
|
||||||
|
"etat": [
|
||||||
|
"retard",
|
||||||
|
"absent"
|
||||||
|
],
|
||||||
|
"moduleimpl_id": "",
|
||||||
|
"est_just": "false"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
filterJustificatifs = {
|
||||||
|
"columns": [
|
||||||
|
"entry_date",
|
||||||
|
"date_debut",
|
||||||
|
"date_fin",
|
||||||
|
"etat",
|
||||||
|
"raison",
|
||||||
|
"fichier"
|
||||||
|
],
|
||||||
|
"filters": {
|
||||||
|
"etat": [
|
||||||
|
"attente",
|
||||||
|
"modifie"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('stats_date_fin').value = assi_date_fin;
|
||||||
|
document.getElementById('stats_date_debut').value = assi_date_debut;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
loadAll();
|
||||||
|
stats();
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.stats-values-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
border: 1px solid #333;
|
||||||
|
padding: 5px 2px;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-values {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-values-item h5 {
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-values-part {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerte {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 5px 0;
|
||||||
|
border-radius: 7px;
|
||||||
|
|
||||||
|
background-color: crimson;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerte.invisible {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerte p {
|
||||||
|
font-size: larger;
|
||||||
|
color: whitesmoke;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.suppr {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -59,6 +59,8 @@
|
|||||||
assi = filterArray(assi, filterAssiduites.filters)
|
assi = filterArray(assi, filterAssiduites.filters)
|
||||||
renderTableAssiduites(currentPageAssiduites, assi);
|
renderTableAssiduites(currentPageAssiduites, assi);
|
||||||
renderPaginationButtons(assi);
|
renderPaginationButtons(assi);
|
||||||
|
|
||||||
|
try { stats() } catch (_) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
const moduleimpls = {}
|
const moduleimpls = {}
|
||||||
@ -109,6 +111,7 @@
|
|||||||
row.appendChild(td)
|
row.appendChild(td)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
row.addEventListener("contextmenu", openContext);
|
row.addEventListener("contextmenu", openContext);
|
||||||
|
|
||||||
tableBodyAssiduites.appendChild(row);
|
tableBodyAssiduites.appendChild(row);
|
||||||
|
@ -132,6 +132,11 @@
|
|||||||
function renderPaginationButtons(array, assi = true) {
|
function renderPaginationButtons(array, assi = true) {
|
||||||
const totalPages = Math.ceil(array.length / itemsPerPage);
|
const totalPages = Math.ceil(array.length / itemsPerPage);
|
||||||
if (totalPages <= 1) {
|
if (totalPages <= 1) {
|
||||||
|
if (assi) {
|
||||||
|
paginationContainerAssiduites.innerHTML = ""
|
||||||
|
} else {
|
||||||
|
paginationContainerJustificatifs.innerHTML = ""
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,14 +144,15 @@
|
|||||||
paginationContainerAssiduites.innerHTML = "<span class='liste_pagination'><button class='pagination_moins'><</button><select id='paginationAssi'></select><button class='pagination_plus'>></button></span>"
|
paginationContainerAssiduites.innerHTML = "<span class='liste_pagination'><button class='pagination_moins'><</button><select id='paginationAssi'></select><button class='pagination_plus'>></button></span>"
|
||||||
paginationContainerAssiduites.querySelector('#paginationAssi')?.addEventListener('change', (e) => {
|
paginationContainerAssiduites.querySelector('#paginationAssi')?.addEventListener('change', (e) => {
|
||||||
currentPageAssiduites = e.target.value;
|
currentPageAssiduites = e.target.value;
|
||||||
renderTableAssiduites(currentPageAssiduites, array);
|
assiduiteCallBack(array);
|
||||||
})
|
})
|
||||||
|
|
||||||
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
|
||||||
renderTableAssiduites(currentPageAssiduites, array);
|
assiduiteCallBack(array);
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -154,21 +160,21 @@
|
|||||||
if (currentPageAssiduites < totalPages) {
|
if (currentPageAssiduites < totalPages) {
|
||||||
currentPageAssiduites++;
|
currentPageAssiduites++;
|
||||||
paginationContainerAssiduites.querySelector('#paginationAssi').value = currentPageAssiduites
|
paginationContainerAssiduites.querySelector('#paginationAssi').value = currentPageAssiduites
|
||||||
renderTableAssiduites(currentPageAssiduites, array);
|
assiduiteCallBack(array);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
paginationContainerJustificatifs.innerHTML = "<span class='liste_pagination'><button class='pagination_moins'><</button><select id='paginationJusti'></select><button class='pagination_plus'>></button></span>"
|
paginationContainerJustificatifs.innerHTML = "<span class='liste_pagination'><button class='pagination_moins'><</button><select id='paginationJusti'></select><button class='pagination_plus'>></button></span>"
|
||||||
paginationContainerJustificatifs.querySelector('#paginationJusti')?.addEventListener('change', (e) => {
|
paginationContainerJustificatifs.querySelector('#paginationJusti')?.addEventListener('change', (e) => {
|
||||||
currentPageJustificatifs = e.target.value;
|
currentPageJustificatifs = e.target.value;
|
||||||
renderTableJustificatifs(currentPageJustificatifs, array);
|
justificatifCallBack(array);
|
||||||
})
|
})
|
||||||
|
|
||||||
paginationContainerJustificatifs.querySelector('.pagination_moins').addEventListener('click', () => {
|
paginationContainerJustificatifs.querySelector('.pagination_moins').addEventListener('click', () => {
|
||||||
if (currentPageJustificatifs > 1) {
|
if (currentPageJustificatifs > 1) {
|
||||||
currentPageJustificatifs--;
|
currentPageJustificatifs--;
|
||||||
paginationContainerJustificatifs.querySelector('#paginationJusti').value = currentPageAssiduites
|
paginationContainerJustificatifs.querySelector('#paginationJusti').value = currentPageAssiduites
|
||||||
renderTableJustificatifs(currentPageJustificatifs, array);
|
justificatifCallBack(array);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -176,7 +182,7 @@
|
|||||||
if (currentPageJustificatifs < totalPages) {
|
if (currentPageJustificatifs < totalPages) {
|
||||||
currentPageJustificatifs++;
|
currentPageJustificatifs++;
|
||||||
paginationContainerJustificatifs.querySelector('#paginationJusti').value = currentPageAssiduites
|
paginationContainerJustificatifs.querySelector('#paginationJusti').value = currentPageAssiduites
|
||||||
renderTableJustificatifs(currentPageJustificatifs, array);
|
justificatifCallBack(array);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -624,6 +630,8 @@
|
|||||||
return "Raison";
|
return "Raison";
|
||||||
case "fichier":
|
case "fichier":
|
||||||
return "Fichier";
|
return "Fichier";
|
||||||
|
case "etudid":
|
||||||
|
return "Etudiant";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,7 +784,7 @@
|
|||||||
margin-left: 2px !important;
|
margin-left: 2px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
.filter-body label {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -57,6 +57,17 @@
|
|||||||
renderPaginationButtons(justi, false);
|
renderPaginationButtons(justi, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getEtudiant(id) {
|
||||||
|
if (id in etuds) {
|
||||||
|
return etuds[id];
|
||||||
|
}
|
||||||
|
getSingleEtud(id);
|
||||||
|
|
||||||
|
return etuds[id];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function renderTableJustificatifs(page, justificatifs) {
|
function renderTableJustificatifs(page, justificatifs) {
|
||||||
generateTableHead(filterJustificatifs.columns, false)
|
generateTableHead(filterJustificatifs.columns, false)
|
||||||
|
|
||||||
@ -85,9 +96,13 @@
|
|||||||
td.textContent = moment.tz(justificatif[k], TIMEZONE).format(`DD/MM/Y HH:mm`)
|
td.textContent = moment.tz(justificatif[k], TIMEZONE).format(`DD/MM/Y HH:mm`)
|
||||||
} else if (k.indexOf('fichier') != -1) {
|
} else if (k.indexOf('fichier') != -1) {
|
||||||
td.textContent = justificatif.fichier ? "Oui" : "Non";
|
td.textContent = justificatif.fichier ? "Oui" : "Non";
|
||||||
|
} else if (k.indexOf('etudid') != -1) {
|
||||||
|
const e = getEtudiant(justificatif.etudid);
|
||||||
|
|
||||||
|
td.textContent = `${e.prenom.capitalize()} ${e.nom.toUpperCase()}`;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
td.textContent = justificatif[k].capitalize()
|
td.textContent = `${justificatif[k]}`.capitalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(td)
|
row.appendChild(td)
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<h2 class="insidebar">Scolarité</h2>
|
<h2 class="insidebar">Scolarité</h2>
|
||||||
<a href="{{url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Semestres</a> <br>
|
<a href="{{url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Semestres</a> <br>
|
||||||
<a href="{{url_for('notes.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Programmes</a> <br>
|
<a href="{{url_for('notes.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Programmes</a> <br>
|
||||||
<a href="{{url_for('absences.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Absences</a> <br>
|
<a href="{{url_for('assiduites.index_html', scodoc_dept=g.scodoc_dept)}}" class="sidebar">Assiduités</a> <br>
|
||||||
|
|
||||||
{% if current_user.has_permission(sco.Permission.ScoUsersAdmin)
|
{% if current_user.has_permission(sco.Permission.ScoUsersAdmin)
|
||||||
or current_user.has_permission(sco.Permission.ScoUsersView)
|
or current_user.has_permission(sco.Permission.ScoUsersView)
|
||||||
@ -73,6 +73,8 @@
|
|||||||
etudid=sco.etud.id) }}">Calendrier</a></li>
|
etudid=sco.etud.id) }}">Calendrier</a></li>
|
||||||
<li><a href="{{ url_for('assiduites.liste_assiduites_etud', scodoc_dept=g.scodoc_dept,
|
<li><a href="{{ url_for('assiduites.liste_assiduites_etud', scodoc_dept=g.scodoc_dept,
|
||||||
etudid=sco.etud.id) }}">Liste</a></li>
|
etudid=sco.etud.id) }}">Liste</a></li>
|
||||||
|
<li><a href="{{ url_for('assiduites.bilan_etud', scodoc_dept=g.scodoc_dept,
|
||||||
|
etudid=sco.etud.id) }}">Bilan</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div> {# /etud-insidebar #}
|
</div> {# /etud-insidebar #}
|
||||||
|
@ -10,7 +10,7 @@ from app.decorators import (
|
|||||||
scodoc,
|
scodoc,
|
||||||
permission_required,
|
permission_required,
|
||||||
)
|
)
|
||||||
from app.models import FormSemestre, Identite, ScoDocSiteConfig, Assiduite
|
from app.models import FormSemestre, Identite, ScoDocSiteConfig, Assiduite, Departement
|
||||||
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
|
||||||
|
|
||||||
@ -125,36 +125,49 @@ class HTMLBuilder:
|
|||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
def index_html():
|
def index_html():
|
||||||
"""Gestionnaire assiduités, page principale"""
|
"""Gestionnaire assiduités, page principale"""
|
||||||
|
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(
|
html_sco_header.sco_header(
|
||||||
page_title="Saisie des assiduités",
|
page_title="Saisie des assiduités",
|
||||||
cssstyles=["css/calabs.css"],
|
javascripts=[
|
||||||
javascripts=["js/calabs.js"],
|
"js/assiduites.js",
|
||||||
|
"libjs/moment.new.min.js",
|
||||||
|
"libjs/moment-timezone.js",
|
||||||
|
],
|
||||||
|
cssstyles=[
|
||||||
|
"css/assiduites.css",
|
||||||
|
],
|
||||||
),
|
),
|
||||||
"""<h2>Traitement des assiduités</h2>
|
"""<h2>Traitement des assiduités</h2>
|
||||||
<p class="help">
|
<p class="help">
|
||||||
Pour saisir des assiduités ou consulter les états, il est recommandé par passer par
|
Pour saisir des assiduités ou consulter les états, il est recommandé par passer par
|
||||||
le semestre concerné (saisie par jours nommés ou par semaines).
|
le semestre concerné (saisie par jour ou saisie différée).
|
||||||
</p>
|
</p>
|
||||||
""",
|
""",
|
||||||
]
|
]
|
||||||
H.append(
|
H.append(
|
||||||
"""<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 concerné:</p>"""
|
choisissez d'abord le concerné:</p>"""
|
||||||
)
|
)
|
||||||
H.append(sco_find_etud.form_search_etud())
|
H.append(sco_find_etud.form_search_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>
|
||||||
"""
|
# """
|
||||||
)
|
# )
|
||||||
|
|
||||||
|
H.append(
|
||||||
|
render_template(
|
||||||
|
"assiduites/pages/bilan_dept.j2",
|
||||||
|
dept_id=g.scodoc_dept_id,
|
||||||
|
annee=scu.annee_scolaire(),
|
||||||
|
),
|
||||||
|
)
|
||||||
H.append(html_sco_header.sco_footer())
|
H.append(html_sco_header.sco_footer())
|
||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
@ -269,6 +282,60 @@ def liste_assiduites_etud():
|
|||||||
).build()
|
).build()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/BilanEtud")
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoAbsChange)
|
||||||
|
def bilan_etud():
|
||||||
|
"""
|
||||||
|
bilan_etud Affichage de toutes les assiduites et justificatifs d'un etudiant
|
||||||
|
Args:
|
||||||
|
etudid (int): l'identifiant de l'étudiant
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: l'html généré
|
||||||
|
"""
|
||||||
|
|
||||||
|
etudid = request.args.get("etudid", -1)
|
||||||
|
etud: Identite = Identite.query.get_or_404(etudid)
|
||||||
|
if etud.dept_id != g.scodoc_dept_id:
|
||||||
|
abort(404, "étudiant inexistant dans ce département")
|
||||||
|
|
||||||
|
header: str = html_sco_header.sco_header(
|
||||||
|
page_title="Bilan de l'assiduité étudiante",
|
||||||
|
init_qtip=True,
|
||||||
|
javascripts=[
|
||||||
|
"js/assiduites.js",
|
||||||
|
"libjs/moment.new.min.js",
|
||||||
|
"libjs/moment-timezone.js",
|
||||||
|
],
|
||||||
|
cssstyles=CSSSTYLES
|
||||||
|
+ [
|
||||||
|
"css/assiduites.css",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
date_debut: str = f"{scu.annee_scolaire()}-09-01"
|
||||||
|
date_fin: str = f"{scu.annee_scolaire()+1}-06-30"
|
||||||
|
|
||||||
|
assi_metric = {
|
||||||
|
"H.": "heure",
|
||||||
|
"J.": "journee",
|
||||||
|
"1/2 J.": "demi",
|
||||||
|
}.get(sco_preferences.get_preference("assi_metrique", dept_id=g.scodoc_dept_id))
|
||||||
|
|
||||||
|
return HTMLBuilder(
|
||||||
|
header,
|
||||||
|
render_template(
|
||||||
|
"assiduites/pages/bilan_etud.j2",
|
||||||
|
sco=ScoData(etud),
|
||||||
|
date_debut=date_debut,
|
||||||
|
date_fin=date_fin,
|
||||||
|
assi_metric=assi_metric,
|
||||||
|
assi_seuil=_get_seuil(),
|
||||||
|
),
|
||||||
|
).build()
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/AjoutJustificatifEtud")
|
@bp.route("/AjoutJustificatifEtud")
|
||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoAbsChange)
|
@permission_required(Permission.ScoAbsChange)
|
||||||
@ -549,7 +616,7 @@ def get_etat_abs_date():
|
|||||||
etat = scu.EtatAssiduite.inverse().get(assi.etat).name
|
etat = scu.EtatAssiduite.inverse().get(assi.etat).name
|
||||||
|
|
||||||
etudiant = {
|
etudiant = {
|
||||||
"nom": f'<a href="{url_for("absences.CalAbs", scodoc_dept=g.scodoc_dept, etudid=etud["etudid"])}"><font color="#A00000">{etud["nomprenom"]}</font></a>',
|
"nom": f'<a href="{url_for("assiduites.calendrier_etud", scodoc_dept=g.scodoc_dept, etudid=etud["etudid"])}"><font color="#A00000">{etud["nomprenom"]}</font></a>',
|
||||||
"etat": etat,
|
"etat": etat,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,3 +844,7 @@ def _str_to_num(string: str):
|
|||||||
|
|
||||||
def get_time(label: str, default: str):
|
def get_time(label: str, default: str):
|
||||||
return _str_to_num(ScoDocSiteConfig.get(label, default))
|
return _str_to_num(ScoDocSiteConfig.get(label, default))
|
||||||
|
|
||||||
|
|
||||||
|
def _get_seuil():
|
||||||
|
return sco_preferences.get_preference("assi_seuil", dept_id=g.scodoc_dept_id)
|
||||||
|
@ -655,22 +655,16 @@ def profile(host, port, length, profile_dir):
|
|||||||
"-m",
|
"-m",
|
||||||
"--morning",
|
"--morning",
|
||||||
help="Spécifie l'heure de début des cours format `hh:mm`",
|
help="Spécifie l'heure de début des cours format `hh:mm`",
|
||||||
default="Heure configurée dans la configuration générale / 08:00 sinon",
|
|
||||||
show_default=True,
|
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"-n",
|
"-n",
|
||||||
"--noon",
|
"--noon",
|
||||||
help="Spécifie l'heure de fin du matin (et donc début de l'après-midi) format `hh:mm`",
|
help="Spécifie l'heure de fin du matin (et donc début de l'après-midi) format `hh:mm`",
|
||||||
default="Heure configurée dans la configuration générale / 13:00 sinon",
|
|
||||||
show_default=True,
|
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"-e",
|
"-e",
|
||||||
"--evening",
|
"--evening",
|
||||||
help="Spécifie l'heure de fin des cours format `hh:mm`",
|
help="Spécifie l'heure de fin des cours format `hh:mm`",
|
||||||
default="Heure configurée dans la configuration générale / 18:00 sinon",
|
|
||||||
show_default=True,
|
|
||||||
)
|
)
|
||||||
@with_appcontext
|
@with_appcontext
|
||||||
def migrate_abs_to_assiduites(
|
def migrate_abs_to_assiduites(
|
||||||
|
@ -228,22 +228,22 @@ def migrate_abs_to_assiduites(
|
|||||||
_glob.DEBUG = debug
|
_glob.DEBUG = debug
|
||||||
|
|
||||||
if morning is None:
|
if morning is None:
|
||||||
_glob.MORNING = ScoDocSiteConfig.get("assi_morning_time", time(8, 0))
|
morning = ScoDocSiteConfig.get("assi_morning_time", time(8, 0))
|
||||||
else:
|
|
||||||
morning: list[str] = morning.split(":")
|
morning: list[str] = morning.split(":")
|
||||||
_glob.MORNING = time(int(morning[0]), int(morning[1]))
|
_glob.MORNING = time(int(morning[0]), int(morning[1]))
|
||||||
|
|
||||||
if noon is None:
|
if noon is None:
|
||||||
_glob.NOON = ScoDocSiteConfig.get("assi_lunch_time", time(13, 0))
|
noon = ScoDocSiteConfig.get("assi_lunch_time", time(13, 0))
|
||||||
else:
|
|
||||||
noon: list[str] = noon.split(":")
|
noon: list[str] = noon.split(":")
|
||||||
_glob.NOON = time(int(noon[0]), int(noon[1]))
|
_glob.NOON = time(int(noon[0]), int(noon[1]))
|
||||||
|
|
||||||
if evening is None:
|
if evening is None:
|
||||||
_glob.EVENING = ScoDocSiteConfig.get("assi_afternoon_time", time(18, 0))
|
evening = ScoDocSiteConfig.get("assi_afternoon_time", time(18, 0))
|
||||||
else:
|
|
||||||
evening: list[str] = evening.split(":")
|
evening: list[str] = evening.split(":")
|
||||||
_glob.EVENING = time(int(evening[0]), int(evening[1]))
|
_glob.EVENING = time(int(evening[0]), int(evening[1]))
|
||||||
|
|
||||||
if dept is None:
|
if dept is None:
|
||||||
prof_total = Profiler("MigrationTotal")
|
prof_total = Profiler("MigrationTotal")
|
||||||
|
Loading…
Reference in New Issue
Block a user