forked from ScoDoc/ScoDoc
Assiduites : ajout préférences
This commit is contained in:
parent
15baf57136
commit
6dc39c25ee
86
app/forms/main/config_assiduites.py
Normal file
86
app/forms/main/config_assiduites.py
Normal file
@ -0,0 +1,86 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# ScoDoc
|
||||
#
|
||||
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
Formulaire configuration Module Assiduités
|
||||
"""
|
||||
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import SubmitField
|
||||
from wtforms.fields.simple import StringField
|
||||
from wtforms.widgets import TimeInput
|
||||
import datetime
|
||||
|
||||
|
||||
class TimeField(StringField):
|
||||
"""HTML5 time input."""
|
||||
|
||||
widget = TimeInput()
|
||||
|
||||
def __init__(self, label=None, validators=None, fmt="%H:%M:%S", **kwargs):
|
||||
super(TimeField, self).__init__(label, validators, **kwargs)
|
||||
self.fmt = fmt
|
||||
self.data = None
|
||||
|
||||
def _value(self):
|
||||
if self.raw_data:
|
||||
return " ".join(self.raw_data)
|
||||
if self.data and isinstance(self.data, str):
|
||||
self.data = datetime.time(*map(int, self.data.split(":")))
|
||||
return self.data and self.data.strftime(self.fmt) or ""
|
||||
|
||||
def process_formdata(self, valuelist):
|
||||
if valuelist:
|
||||
time_str = " ".join(valuelist)
|
||||
try:
|
||||
components = time_str.split(":")
|
||||
hour = 0
|
||||
minutes = 0
|
||||
seconds = 0
|
||||
if len(components) in range(2, 4):
|
||||
hour = int(components[0])
|
||||
minutes = int(components[1])
|
||||
|
||||
if len(components) == 3:
|
||||
seconds = int(components[2])
|
||||
else:
|
||||
raise ValueError
|
||||
self.data = datetime.time(hour, minutes, seconds)
|
||||
except ValueError:
|
||||
self.data = None
|
||||
raise ValueError(self.gettext("Not a valid time string"))
|
||||
|
||||
|
||||
class ConfigAssiduitesForm(FlaskForm):
|
||||
"Formulaire paramétrage Module Assiduités"
|
||||
|
||||
morning_time = TimeField("Début de la journée")
|
||||
lunch_time = TimeField("Heure de midi (date pivot entre Matin et Après Midi)")
|
||||
afternoon_time = TimeField("Fin de la journée")
|
||||
|
||||
submit = SubmitField("Valider")
|
||||
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})
|
@ -8,6 +8,8 @@ from app import current_app, db, log
|
||||
from app.comp import bonus_spo
|
||||
from app.scodoc import sco_utils as scu
|
||||
|
||||
from datetime import time
|
||||
|
||||
from app.scodoc.codes_cursus import (
|
||||
ABAN,
|
||||
ABL,
|
||||
@ -94,6 +96,10 @@ class ScoDocSiteConfig(db.Model):
|
||||
"cas_logout_route": str,
|
||||
"cas_validate_route": str,
|
||||
"cas_attribute_id": str,
|
||||
# Assiduités
|
||||
"morning_time": str,
|
||||
"lunch_time": str,
|
||||
"afternoon_time": str,
|
||||
}
|
||||
|
||||
def __init__(self, name, value):
|
||||
|
@ -204,6 +204,7 @@ PREF_CATEGORIES = (
|
||||
("misc", {"title": "Divers"}),
|
||||
("apc", {"title": "BUT et Approches par Compétences"}),
|
||||
("abs", {"title": "Suivi des absences", "related": ("bul",)}),
|
||||
("assi", {"title": "Gestion de l'assiduité"}),
|
||||
("portal", {"title": "Liaison avec portail (Apogée, etc)"}),
|
||||
("apogee", {"title": "Exports Apogée"}),
|
||||
(
|
||||
@ -598,6 +599,38 @@ class BasePreferences(object):
|
||||
"category": "abs",
|
||||
},
|
||||
),
|
||||
# Assiduités
|
||||
(
|
||||
"forcer_module",
|
||||
{
|
||||
"initvalue": 0,
|
||||
"title": "Forcer la déclaration du module.",
|
||||
"input_type": "boolcheckbox",
|
||||
"labels": ["non", "oui"],
|
||||
"category": "assi",
|
||||
},
|
||||
),
|
||||
(
|
||||
"forcer_present",
|
||||
{
|
||||
"initvalue": 0,
|
||||
"title": "Forcer l'appel des présents",
|
||||
"input_type": "boolcheckbox",
|
||||
"labels": ["non", "oui"],
|
||||
"category": "assi",
|
||||
},
|
||||
),
|
||||
(
|
||||
"etat_defaut",
|
||||
{
|
||||
"initvalue": "aucun",
|
||||
"input_type": "menu",
|
||||
"labels": ["aucun", "present", "retard", "absent"],
|
||||
"allowed_values": ["aucun", "present", "retard", "absent"],
|
||||
"title": "Définir l'état par défaut",
|
||||
"category": "assi",
|
||||
},
|
||||
),
|
||||
# portal
|
||||
(
|
||||
"portal_url",
|
||||
@ -1700,7 +1733,7 @@ class BasePreferences(object):
|
||||
(
|
||||
"feuille_releve_abs_taille",
|
||||
{
|
||||
"initvalue": "A3",
|
||||
"initvalue": "A4",
|
||||
"input_type": "menu",
|
||||
"labels": ["A3", "A4"],
|
||||
"allowed_values": ["A3", "A4"],
|
||||
|
@ -88,6 +88,20 @@ function validateSelectors() {
|
||||
);
|
||||
});
|
||||
|
||||
if (getModuleImplId() == null && forceModule) {
|
||||
const HTML = `
|
||||
<p>Attention, le module doit obligatoirement être renseigné.</p>
|
||||
<p>Cela vient de la configuration du semestre ou plus largement du département.</p>
|
||||
<p>Si c'est une erreur, veuillez voir avec le ou les responsables de votre scodoc.</p>
|
||||
`;
|
||||
|
||||
const content = document.createElement("div");
|
||||
content.innerHTML = HTML;
|
||||
|
||||
openAlertModal("Sélection du module", content);
|
||||
return;
|
||||
}
|
||||
|
||||
getAssiduitesFromEtuds(true);
|
||||
|
||||
document.querySelector(".selectors").disabled = true;
|
||||
@ -1133,14 +1147,16 @@ function createMiniTimeline(assiduitesArray) {
|
||||
}
|
||||
};
|
||||
|
||||
getJustificatifFromPeriod(
|
||||
{
|
||||
deb: new moment.tz(assiduité.date_debut, TIMEZONE),
|
||||
fin: new moment.tz(assiduité.date_fin, TIMEZONE),
|
||||
},
|
||||
assiduité.etudid,
|
||||
action
|
||||
);
|
||||
if (assiduité.etudid) {
|
||||
getJustificatifFromPeriod(
|
||||
{
|
||||
deb: new moment.tz(assiduité.date_debut, TIMEZONE),
|
||||
fin: new moment.tz(assiduité.date_fin, TIMEZONE),
|
||||
},
|
||||
assiduité.etudid,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
switch (assiduité.etat) {
|
||||
case "PRESENT":
|
||||
@ -1905,7 +1921,9 @@ function fastJustify(assiduite) {
|
||||
);
|
||||
}
|
||||
};
|
||||
getJustificatifFromPeriod(period, assiduite.etudid, action);
|
||||
if (assiduite.etudid) {
|
||||
getJustificatifFromPeriod(period, assiduite.etudid, action);
|
||||
}
|
||||
}
|
||||
|
||||
function justifyAssiduite(assiduite_id, justified) {
|
||||
|
28
app/templates/assiduites/config_assiduites.j2
Normal file
28
app/templates/assiduites/config_assiduites.j2
Normal file
@ -0,0 +1,28 @@
|
||||
{% extends "base.j2" %}
|
||||
{% import 'bootstrap/wtf.html' as wtf %}
|
||||
|
||||
{% block app_content %}
|
||||
<h1>Configuration du Module d'assiduité</h1>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
|
||||
<form class="form form-horizontal" method="post" enctype="multipart/form-data" role="form">
|
||||
{{ form.hidden_tag() }}
|
||||
{{ wtf.form_errors(form, hiddens="only") }}
|
||||
|
||||
{{ wtf.form_field(form.morning_time) }}
|
||||
{{ wtf.form_field(form.lunch_time) }}
|
||||
{{ wtf.form_field(form.afternoon_time) }}
|
||||
<div class="form-group">
|
||||
{{ wtf.form_field(form.submit) }}
|
||||
{{ wtf.form_field(form.cancel) }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
@ -49,9 +49,9 @@
|
||||
</div>
|
||||
|
||||
<div class="btn_group">
|
||||
<button class="btn" onclick="setTimeLineTimes(8,18)">Journée</button>
|
||||
<button class="btn" onclick="setTimeLineTimes(8,13)">Matin</button>
|
||||
<button class="btn" onclick="setTimeLineTimes(13,18)">Après-midi</button>
|
||||
<button class="btn" onclick="setTimeLineTimes({{morning}},{{afternoon}})">Journée</button>
|
||||
<button class="btn" onclick="setTimeLineTimes({{morning}},{{lunch}})">Matin</button>
|
||||
<button class="btn" onclick="setTimeLineTimes({{lunch}},{{afternoon}})">Après-midi</button>
|
||||
</div>
|
||||
|
||||
<div class="etud_holder">
|
||||
@ -94,6 +94,9 @@
|
||||
|
||||
}
|
||||
|
||||
let forceModule = "{{ forcer_module }}"
|
||||
forceModule = forceModule == "True" ? true : false
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
@ -73,5 +73,8 @@
|
||||
updateDate();
|
||||
setupDate();
|
||||
setupTimeLine();
|
||||
|
||||
let forceModule = "{{ forcer_module }}"
|
||||
forceModule = forceModule == "True" ? true : false
|
||||
</script>
|
||||
</section>
|
@ -9,31 +9,60 @@
|
||||
|
||||
const timelineContainer = document.querySelector(".timeline-container");
|
||||
const periodTimeLine = document.querySelector(".period");
|
||||
const t_start = {{ t_start }}
|
||||
const t_end = {{ t_end }}
|
||||
|
||||
function createTicks() {
|
||||
for (let i = 8; i <= 18; i++) {
|
||||
let i = t_start
|
||||
|
||||
while (i <= t_end) {
|
||||
const hourTick = document.createElement("div");
|
||||
hourTick.classList.add("tick", "hour");
|
||||
hourTick.style.left = `${((i - 8) / 10) * 100}%`;
|
||||
hourTick.style.left = `${((i - t_start) / (t_end - t_start)) * 100}%`;
|
||||
timelineContainer.appendChild(hourTick);
|
||||
|
||||
const tickLabel = document.createElement("div");
|
||||
tickLabel.classList.add("tick-label");
|
||||
tickLabel.style.left = `${((i - 8) / 10) * 100}%`;
|
||||
tickLabel.textContent = i < 10 ? `0${i}:00` : `${i}:00`;
|
||||
tickLabel.style.left = `${((i - t_start) / (t_end - t_start)) * 100}%`;
|
||||
tickLabel.textContent = numberToTime(i);
|
||||
timelineContainer.appendChild(tickLabel);
|
||||
|
||||
if (i < 18) {
|
||||
for (let j = 1; j < 4; j++) {
|
||||
const quarterTick = document.createElement("div");
|
||||
quarterTick.classList.add("tick", "quarter");
|
||||
quarterTick.style.left = `${((i - 8 + j / 4) / 10) * 100}%`;
|
||||
timelineContainer.appendChild(quarterTick);
|
||||
if (i < t_end) {
|
||||
let j = Math.floor(i + 1)
|
||||
|
||||
while (i < j) {
|
||||
i += 0.25;
|
||||
|
||||
if (i <= t_end) {
|
||||
const quarterTick = document.createElement("div");
|
||||
quarterTick.classList.add("tick", "quarter");
|
||||
quarterTick.style.left = `${computePercentage(i, t_start)}%`;
|
||||
timelineContainer.appendChild(quarterTick);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function numberToTime(num) {
|
||||
const integer = Math.floor(num)
|
||||
const decimal = (num % 1) * 60
|
||||
|
||||
let dec = `:${decimal}`
|
||||
if (decimal < 10) {
|
||||
dec = `:0${decimal}`
|
||||
}
|
||||
|
||||
let int = `${integer}`
|
||||
if (integer < 10) {
|
||||
int = `0${integer}`
|
||||
}
|
||||
|
||||
return int + dec
|
||||
|
||||
}
|
||||
|
||||
function snapToQuarter(value) {
|
||||
return Math.round(value * 4) / 4;
|
||||
}
|
||||
@ -119,18 +148,28 @@
|
||||
const leftPercentage = parseFloat(periodTimeLine.style.left);
|
||||
const widthPercentage = parseFloat(periodTimeLine.style.width);
|
||||
|
||||
const startHour = (leftPercentage / 100) * 10 + 8;
|
||||
const endHour = ((leftPercentage + widthPercentage) / 100) * 10 + 8;
|
||||
const startHour = (leftPercentage / 100) * (t_end - t_start) + t_start;
|
||||
const endHour = ((leftPercentage + widthPercentage) / 100) * (t_end - t_start) + t_start;
|
||||
|
||||
const startValue = Math.round(startHour * 4) / 4;
|
||||
const endValue = Math.round(endHour * 4) / 4;
|
||||
|
||||
return [startValue, endValue]
|
||||
const computedValues = [Math.max(startValue, t_start), Math.min(t_end, endValue)]
|
||||
|
||||
if (computedValues[0] > t_end || computedValues[1] < t_start) {
|
||||
return [8, 10]
|
||||
}
|
||||
|
||||
if (computedValues[1] - computedValues[0] <= 0.25 && computedValues[1] < t_end - 0.25) {
|
||||
computedValues[1] += 0.25;
|
||||
}
|
||||
|
||||
return computedValues
|
||||
}
|
||||
|
||||
function setPeriodValues(deb, fin) {
|
||||
let leftPercentage = (deb - 8) / 10 * 100
|
||||
let widthPercentage = (fin - deb) / 10 * 100
|
||||
let leftPercentage = (deb - t_start) / (t_end - t_start) * 100
|
||||
let widthPercentage = (fin - deb) / (t_end - t_start) * 100
|
||||
periodTimeLine.style.left = `${leftPercentage}%`
|
||||
periodTimeLine.style.width = `${widthPercentage}%`
|
||||
|
||||
@ -140,12 +179,13 @@
|
||||
|
||||
function snapHandlesToQuarters() {
|
||||
const periodValues = getPeriodValues();
|
||||
let lef = Math.min((periodValues[0] - 8) * 10, 97.5)
|
||||
let lef = Math.min(computePercentage(periodValues[0], t_start), computePercentage(t_end, 0.25))
|
||||
if (lef < 0) {
|
||||
lef = 0;
|
||||
}
|
||||
const left = `${lef}%`
|
||||
let wid = Math.max((periodValues[1] - periodValues[0]) * 10, 2.5)
|
||||
|
||||
let wid = Math.max(computePercentage(periodValues[1], periodValues[0]), computePercentage(0.25, 0))
|
||||
if (wid > 100) {
|
||||
wid = 100;
|
||||
}
|
||||
@ -154,7 +194,12 @@
|
||||
periodTimeLine.style.width = width;
|
||||
}
|
||||
|
||||
function computePercentage(a, b) {
|
||||
return ((a - b) / (t_end - t_start)) * 100
|
||||
}
|
||||
|
||||
createTicks();
|
||||
setPeriodValues(8, 9)
|
||||
|
||||
</script>
|
||||
<style>
|
||||
|
@ -52,20 +52,25 @@
|
||||
<p><a class="stdlink" href="{{url_for('scodoc.config_codes_decisions')}}">configuration des codes de décision</a>
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h2>Assiduités</h2>
|
||||
<p><a class="stdlink" href="{{url_for('scodoc.config_assiduites')}}">configuration du module d'assiduités</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<h2>Utilisateurs et CAS</h2>
|
||||
<section>
|
||||
<div>
|
||||
🏰 <a class="stdlink" href="{{url_for('scodoc.config_cas')}}">Configuration du service CAS</a>
|
||||
🏰 <a class="stdlink" href="{{url_for('scodoc.config_cas')}}">Configuration du service CAS</a>
|
||||
</div>
|
||||
<div style="margin-top: 16px;">
|
||||
🧑🏾🤝🧑🏼 <a class="stdlink" href="{{ url_for('auth.cas_users_import_config') }}">
|
||||
Configurer les comptes utilisateurs pour le CAS</a>
|
||||
🧑🏾🤝🧑🏼 <a class="stdlink" href="{{ url_for('auth.cas_users_import_config') }}">
|
||||
Configurer les comptes utilisateurs pour le CAS</a>
|
||||
</div>
|
||||
<div style="margin-top: 16px;">
|
||||
🛟 <a class="stdlink" href="{{url_for('auth.reset_standard_roles_permissions')}}">Remettre
|
||||
🛟 <a class="stdlink" href="{{url_for('auth.reset_standard_roles_permissions')}}">Remettre
|
||||
les permissions des rôles standards à leurs valeurs par défaut</a>
|
||||
(efface les modifications apportées aux rôles)
|
||||
(efface les modifications apportées aux rôles)
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
@ -10,7 +10,7 @@ from app.decorators import (
|
||||
scodoc,
|
||||
permission_required,
|
||||
)
|
||||
from app.models import FormSemestre, Identite
|
||||
from app.models import FormSemestre, Identite, ScoDocSiteConfig
|
||||
from app.views import assiduites_bp as bp
|
||||
from app.views import ScoData
|
||||
|
||||
@ -190,6 +190,12 @@ def signal_assiduites_etud():
|
||||
],
|
||||
)
|
||||
|
||||
# Gestion des horaires (journée, matin, soir)
|
||||
|
||||
morning = get_time("assi_morning_time", "08:00:00")
|
||||
lunch = get_time("assi_lunch_time", "13:00:00")
|
||||
afternoon = get_time("assi_afternoon_time", "18:00:00")
|
||||
|
||||
return HTMLBuilder(
|
||||
header,
|
||||
render_template("assiduites/minitimeline.j2"),
|
||||
@ -197,10 +203,27 @@ def signal_assiduites_etud():
|
||||
"assiduites/signal_assiduites_etud.j2",
|
||||
sco=ScoData(etud),
|
||||
date=datetime.date.today().isoformat(),
|
||||
morning=morning,
|
||||
lunch=lunch,
|
||||
afternoon=afternoon,
|
||||
forcer_module=sco_preferences.get_preference(
|
||||
"forcer_module", dept_id=g.scodoc_dept_id
|
||||
),
|
||||
),
|
||||
).build()
|
||||
|
||||
|
||||
def _str_to_num(string: str):
|
||||
parts = [*map(float, string.split(":"))]
|
||||
hour = parts[0]
|
||||
minutes = round(parts[1] / 60 * 4) / 4
|
||||
return hour + minutes
|
||||
|
||||
|
||||
def get_time(label: str, default: str):
|
||||
return _str_to_num(ScoDocSiteConfig.get(label, default))
|
||||
|
||||
|
||||
@bp.route("/ListeAssiduitesEtud")
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoAbsChange)
|
||||
@ -373,6 +396,11 @@ def signal_assiduites_group():
|
||||
timeline=_timeline(),
|
||||
formsemestre_date_debut=str(formsemestre.date_debut),
|
||||
formsemestre_date_fin=str(formsemestre.date_fin),
|
||||
forcer_module=sco_preferences.get_preference(
|
||||
"forcer_module",
|
||||
formsemestre_id=formsemestre_id,
|
||||
dept_id=g.scodoc_dept_id,
|
||||
),
|
||||
),
|
||||
html_sco_header.sco_footer(),
|
||||
).build()
|
||||
@ -416,4 +444,8 @@ def _module_selector(
|
||||
|
||||
|
||||
def _timeline() -> HTMLElement:
|
||||
return render_template("assiduites/timeline.j2")
|
||||
return render_template(
|
||||
"assiduites/timeline.j2",
|
||||
t_start=get_time("assi_morning_time", "08:00:00"),
|
||||
t_end=get_time("assi_afternoon_time", "18:00:00"),
|
||||
)
|
||||
|
@ -64,6 +64,7 @@ from app.forms.main import config_logos, config_main
|
||||
from app.forms.main.create_dept import CreateDeptForm
|
||||
from app.forms.main.config_apo import CodesDecisionsForm
|
||||
from app.forms.main.config_cas import ConfigCASForm
|
||||
from app.forms.main.config_assiduites import ConfigAssiduitesForm
|
||||
from app import models
|
||||
from app.models import Departement, Identite
|
||||
from app.models import departements
|
||||
@ -188,6 +189,39 @@ def config_cas():
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/ScoDoc/config_assiduites", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def config_assiduites():
|
||||
"""Form config Assiduites"""
|
||||
form = ConfigAssiduitesForm()
|
||||
if request.method == "POST" and form.cancel.data: # cancel button
|
||||
return redirect(url_for("scodoc.index"))
|
||||
if form.validate_on_submit():
|
||||
if ScoDocSiteConfig.set("assi_morning_time", form.data["morning_time"]):
|
||||
flash("Heure du début de la journée enregistrée")
|
||||
if ScoDocSiteConfig.set("assi_lunch_time", form.data["lunch_time"]):
|
||||
flash("Heure de midi enregistrée")
|
||||
if ScoDocSiteConfig.set("assi_afternoon_time", form.data["afternoon_time"]):
|
||||
flash("Heure de fin de la journée enregistrée")
|
||||
return redirect(url_for("scodoc.configuration"))
|
||||
|
||||
elif request.method == "GET":
|
||||
form.morning_time.data = ScoDocSiteConfig.get(
|
||||
"assi_morning_time", datetime.time(8, 0, 0)
|
||||
)
|
||||
form.lunch_time.data = ScoDocSiteConfig.get(
|
||||
"assi_lunch_time", datetime.time(13, 0, 0)
|
||||
)
|
||||
form.afternoon_time.data = ScoDocSiteConfig.get(
|
||||
"assi_afternoon_time", datetime.time(18, 0, 0)
|
||||
)
|
||||
return render_template(
|
||||
"assiduites/config_assiduites.j2",
|
||||
form=form,
|
||||
title="Configuration du module Assiduités",
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/ScoDoc/config_codes_decisions", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def config_codes_decisions():
|
||||
|
@ -655,21 +655,21 @@ def profile(host, port, length, profile_dir):
|
||||
"-m",
|
||||
"--morning",
|
||||
help="Spécifie l'heure de début des cours format `hh:mm`",
|
||||
default="08h00",
|
||||
default="Heure configurée dans la configuration générale / 08:00 sinon",
|
||||
show_default=True,
|
||||
)
|
||||
@click.option(
|
||||
"-n",
|
||||
"--noon",
|
||||
help="Spécifie l'heure de fin du matin (et donc début de l'après-midi) format `hh:mm`",
|
||||
default="12h00",
|
||||
default="Heure configurée dans la configuration générale / 13:00 sinon",
|
||||
show_default=True,
|
||||
)
|
||||
@click.option(
|
||||
"-e",
|
||||
"--evening",
|
||||
help="Spécifie l'heure de fin des cours format `hh:mm`",
|
||||
default="18h00",
|
||||
default="Heure configurée dans la configuration générale / 18:00 sinon",
|
||||
show_default=True,
|
||||
)
|
||||
@with_appcontext
|
||||
|
@ -16,6 +16,9 @@ from app.models import (
|
||||
Justificatif,
|
||||
ModuleImplInscription,
|
||||
)
|
||||
|
||||
from app.models.config import ScoDocSiteConfig
|
||||
|
||||
from app.models.assiduites import (
|
||||
compute_assiduites_justified,
|
||||
)
|
||||
@ -181,7 +184,6 @@ class _Statistics:
|
||||
"""Comptage des statistiques"""
|
||||
stats: dict = {"total": self.object["total"]}
|
||||
for year, item in self.object.items():
|
||||
|
||||
if year == "total":
|
||||
continue
|
||||
|
||||
@ -226,21 +228,21 @@ def migrate_abs_to_assiduites(
|
||||
_glob.DEBUG = debug
|
||||
|
||||
if morning is None:
|
||||
_glob.MORNING = time(8, 0)
|
||||
_glob.MORNING = ScoDocSiteConfig.get("assi_morning_time", time(8, 0))
|
||||
else:
|
||||
morning: list[str] = morning.split("h")
|
||||
morning: list[str] = morning.split(":")
|
||||
_glob.MORNING = time(int(morning[0]), int(morning[1]))
|
||||
|
||||
if noon is None:
|
||||
_glob.NOON = time(12, 0)
|
||||
_glob.NOON = ScoDocSiteConfig.get("assi_lunch_time", time(13, 0))
|
||||
else:
|
||||
noon: list[str] = noon.split("h")
|
||||
noon: list[str] = noon.split(":")
|
||||
_glob.NOON = time(int(noon[0]), int(noon[1]))
|
||||
|
||||
if evening is None:
|
||||
_glob.EVENING = time(18, 0)
|
||||
_glob.EVENING = ScoDocSiteConfig.get("assi_afternoon_time", time(18, 0))
|
||||
else:
|
||||
evening: list[str] = evening.split("h")
|
||||
evening: list[str] = evening.split(":")
|
||||
_glob.EVENING = time(int(evening[0]), int(evening[1]))
|
||||
|
||||
if dept is None:
|
||||
@ -379,7 +381,6 @@ def migrate_dept(dept_name: str, stats: _Statistics, time_elapsed: Profiler):
|
||||
|
||||
|
||||
def _from_abs_to_assiduite_justificatif(_abs: Absence):
|
||||
|
||||
if _abs.etudid not in _glob.CURRENT_ETU:
|
||||
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
||||
if etud is None:
|
||||
|
Loading…
Reference in New Issue
Block a user