forked from ScoDoc/ScoDoc
Merge branch 'main96' of https://scodoc.org/git/iziram/ScoDoc
This commit is contained in:
commit
ca12519f1c
@ -4,9 +4,9 @@ Ecrit par Matthias Hartmann.
|
|||||||
from datetime import date, datetime, time, timedelta
|
from datetime import date, datetime, time, timedelta
|
||||||
from pytz import UTC
|
from pytz import UTC
|
||||||
|
|
||||||
from app import log
|
from app import log, db
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.models.assiduites import Assiduite, Justificatif
|
from app.models.assiduites import Assiduite, Justificatif, compute_assiduites_justified
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.models.formsemestre import FormSemestre, FormSemestreInscription
|
from app.models.formsemestre import FormSemestre, FormSemestreInscription
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
@ -141,11 +141,11 @@ class CountCalculator:
|
|||||||
self.hours += finish_hours.total_seconds() / 3600
|
self.hours += finish_hours.total_seconds() / 3600
|
||||||
self.hours += self.hour_per_day - (start_hours.total_seconds() / 3600)
|
self.hours += self.hour_per_day - (start_hours.total_seconds() / 3600)
|
||||||
|
|
||||||
def compute_assiduites(self, assiduites: Assiduite):
|
def compute_assiduites(self, assiduites: Query or list):
|
||||||
"""Calcule les métriques pour la collection d'assiduité donnée"""
|
"""Calcule les métriques pour la collection d'assiduité donnée"""
|
||||||
assi: Assiduite
|
assi: Assiduite
|
||||||
assiduites: list[Assiduite] = (
|
assiduites: list[Assiduite] = (
|
||||||
assiduites.all() if isinstance(assiduites, Assiduite) else assiduites
|
assiduites.all() if isinstance(assiduites, Query) else assiduites
|
||||||
)
|
)
|
||||||
for assi in assiduites:
|
for assi in assiduites:
|
||||||
self.count += 1
|
self.count += 1
|
||||||
@ -408,6 +408,42 @@ def get_all_justified(
|
|||||||
return after
|
return after
|
||||||
|
|
||||||
|
|
||||||
|
def create_absence(
|
||||||
|
date_debut: datetime,
|
||||||
|
date_fin: datetime,
|
||||||
|
etudid: int,
|
||||||
|
description: str = None,
|
||||||
|
est_just: bool = False,
|
||||||
|
) -> int:
|
||||||
|
etud: Identite = Identite.query.filter_by(etudid=etudid).first_or_404()
|
||||||
|
assiduite_unique: Assiduite = Assiduite.create_assiduite(
|
||||||
|
etud=etud,
|
||||||
|
date_debut=date_debut,
|
||||||
|
date_fin=date_fin,
|
||||||
|
etat=scu.EtatAssiduite.ABSENT,
|
||||||
|
description=description,
|
||||||
|
)
|
||||||
|
db.session.add(assiduite_unique)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
if est_just:
|
||||||
|
justi = Justificatif.create_justificatif(
|
||||||
|
etud=etud,
|
||||||
|
date_debut=date_debut,
|
||||||
|
date_fin=date_fin,
|
||||||
|
etat=scu.EtatJustificatif.VALIDE,
|
||||||
|
raison=description,
|
||||||
|
)
|
||||||
|
db.session.add(justi)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
compute_assiduites_justified(etud.id, [justi])
|
||||||
|
|
||||||
|
calculator: CountCalculator = CountCalculator()
|
||||||
|
calculator.compute_assiduites([assiduite_unique])
|
||||||
|
return calculator.to_dict()["demi"]
|
||||||
|
|
||||||
|
|
||||||
# Gestion du cache
|
# Gestion du cache
|
||||||
def get_assiduites_count(etudid: int, sem: dict) -> tuple[int, int]:
|
def get_assiduites_count(etudid: int, sem: dict) -> tuple[int, int]:
|
||||||
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
||||||
|
@ -833,7 +833,7 @@ def tab_absences_html(groups_infos, etat=None):
|
|||||||
"<li>",
|
"<li>",
|
||||||
form_choix_jour_saisie_hebdo(groups_infos),
|
form_choix_jour_saisie_hebdo(groups_infos),
|
||||||
"</li>",
|
"</li>",
|
||||||
f"""<li><a href="{
|
f"""<li><a class="stdlink" href="{
|
||||||
url_for("assiduites.visu_assi_group", scodoc_dept=g.scodoc_dept, group_ids=group_ids, date_debut=formsemestre.date_debut.isoformat(), date_fin=formsemestre.date_fin.isoformat())
|
url_for("assiduites.visu_assi_group", scodoc_dept=g.scodoc_dept, group_ids=group_ids, date_debut=formsemestre.date_debut.isoformat(), date_fin=formsemestre.date_fin.isoformat())
|
||||||
}">État des assiduités du groupe</a></li>""",
|
}">État des assiduités du groupe</a></li>""",
|
||||||
"</ul>",
|
"</ul>",
|
||||||
@ -890,76 +890,38 @@ def form_choix_jour_saisie_hebdo(groups_infos, moduleimpl_id=None):
|
|||||||
authuser = current_user
|
authuser = current_user
|
||||||
if not authuser.has_permission(Permission.ScoAbsChange):
|
if not authuser.has_permission(Permission.ScoAbsChange):
|
||||||
return ""
|
return ""
|
||||||
sem = groups_infos.formsemestre
|
return f"""
|
||||||
first_monday = sco_cal.ddmmyyyy(sem["date_debut"]).prev_monday()
|
<button onclick="window.location='{
|
||||||
today_idx = datetime.date.today().weekday()
|
url_for(
|
||||||
|
"assiduites.signal_assiduites_group",
|
||||||
FA = [] # formulaire avec menu saisi absences
|
scodoc_dept=g.scodoc_dept,
|
||||||
FA.append(
|
group_ids=",".join(map(str,groups_infos.group_ids)),
|
||||||
# TODO-ASSIDUITE et utiliser url_for... (was Absences/SignaleAbsenceGrSemestre)
|
jour=datetime.date.today().isoformat(),
|
||||||
'<form id="form_choix_jour_saisie_hebdo" action="XXX" method="get">'
|
formsemestre_id=groups_infos.formsemestre_id,
|
||||||
)
|
moduleimpl_id="" if moduleimpl_id is None else moduleimpl_id
|
||||||
FA.append('<input type="hidden" name="datefin" value="%(date_fin)s"/>' % sem)
|
)
|
||||||
FA.append(groups_infos.get_form_elem())
|
}';">Saisie du jour</button>
|
||||||
if moduleimpl_id:
|
"""
|
||||||
FA.append(
|
|
||||||
'<input type="hidden" name="moduleimpl_id" value="%s"/>' % moduleimpl_id
|
|
||||||
)
|
|
||||||
FA.append('<input type="hidden" name="destination" value=""/>')
|
|
||||||
|
|
||||||
FA.append(
|
|
||||||
"""<input type="button" onclick="$('#form_choix_jour_saisie_hebdo')[0].destination.value=get_current_url(); $('#form_choix_jour_saisie_hebdo').submit();" value="Saisir absences du (NON DISPONIBLE) "/>"""
|
|
||||||
)
|
|
||||||
FA.append("""<select name="datedebut">""")
|
|
||||||
date = first_monday
|
|
||||||
i = 0
|
|
||||||
for jour in sco_cal.day_names():
|
|
||||||
if i == today_idx:
|
|
||||||
sel = "selected"
|
|
||||||
else:
|
|
||||||
sel = ""
|
|
||||||
i += 1
|
|
||||||
FA.append('<option value="%s" %s>%s</option>' % (date, sel, jour))
|
|
||||||
date = date.next_day()
|
|
||||||
FA.append("</select>")
|
|
||||||
FA.append("</form>")
|
|
||||||
return "\n".join(FA)
|
|
||||||
|
|
||||||
|
|
||||||
# Ajout Le Havre
|
# Saisie de l'assiduité par semaine
|
||||||
# Formulaire saisie absences semaine
|
|
||||||
def form_choix_saisie_semaine(groups_infos):
|
def form_choix_saisie_semaine(groups_infos):
|
||||||
authuser = current_user
|
authuser = current_user
|
||||||
if not authuser.has_permission(Permission.ScoAbsChange):
|
if not authuser.has_permission(Permission.ScoAbsChange):
|
||||||
return ""
|
return ""
|
||||||
# construit l'URL "destination"
|
|
||||||
# (a laquelle on revient apres saisie absences)
|
|
||||||
query_args = parse_qs(request.query_string)
|
query_args = parse_qs(request.query_string)
|
||||||
moduleimpl_id = query_args.get("moduleimpl_id", [""])[0]
|
moduleimpl_id = query_args.get("moduleimpl_id", [None])[0]
|
||||||
if "head_message" in query_args:
|
semaine = datetime.date.today().isocalendar().week
|
||||||
del query_args["head_message"]
|
return f"""
|
||||||
destination = "%s?%s" % (
|
<button onclick="window.location='{url_for(
|
||||||
request.base_url,
|
"assiduites.signal_assiduites_diff",
|
||||||
urllib.parse.urlencode(query_args, True),
|
group_ids=",".join(map(str,groups_infos.group_ids)),
|
||||||
)
|
semaine=semaine,
|
||||||
destination = destination.replace(
|
scodoc_dept=g.scodoc_dept,
|
||||||
"%", "%%"
|
formsemestre_id=groups_infos.formsemestre_id,
|
||||||
) # car ici utilisee dans un format string !
|
moduleimpl_id=moduleimpl_id
|
||||||
|
)}';">Saisie à la semaine</button>
|
||||||
DateJour = time.strftime("%d/%m/%Y")
|
"""
|
||||||
datelundi = sco_cal.ddmmyyyy(DateJour).prev_monday()
|
|
||||||
FA = [] # formulaire avec menu saisie hebdo des absences
|
|
||||||
# XXX TODO-ASSIDUITE et utiliser un POST
|
|
||||||
FA.append('<form action="Absences/SignaleAbsenceGrHebdo" method="get">')
|
|
||||||
FA.append('<input type="hidden" name="datelundi" value="%s"/>' % datelundi)
|
|
||||||
FA.append('<input type="hidden" name="moduleimpl_id" value="%s"/>' % moduleimpl_id)
|
|
||||||
FA.append('<input type="hidden" name="destination" value="%s"/>' % destination)
|
|
||||||
FA.append(groups_infos.get_form_elem())
|
|
||||||
FA.append(
|
|
||||||
'<input type="submit" class="button" value="Saisie à la semaine (NON DISPONIBLE)" />'
|
|
||||||
) # XXX
|
|
||||||
FA.append("</form>")
|
|
||||||
return "\n".join(FA)
|
|
||||||
|
|
||||||
|
|
||||||
def export_groups_as_moodle_csv(formsemestre_id=None):
|
def export_groups_as_moodle_csv(formsemestre_id=None):
|
||||||
|
@ -331,6 +331,21 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
}&formsemestre_id={formsemestre.id}
|
}&formsemestre_id={formsemestre.id}
|
||||||
&moduleimpl_id={moduleimpl_id}
|
&moduleimpl_id={moduleimpl_id}
|
||||||
"
|
"
|
||||||
|
>Saisie Absences journée</a></span>
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
H.append(
|
||||||
|
f"""
|
||||||
|
<span class="moduleimpl_abs_link"><a class="stdlink" href="{
|
||||||
|
url_for(
|
||||||
|
"assiduites.signal_assiduites_group",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
group_ids=group_id,
|
||||||
|
jour=datetime.date.today().isoformat(),
|
||||||
|
formsemestre_id=formsemestre.id,
|
||||||
|
moduleimpl_id="" if moduleimpl_id is None else moduleimpl_id
|
||||||
|
)}"
|
||||||
>Saisie Absences hebdo</a></span>
|
>Saisie Absences hebdo</a></span>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@ -56,6 +56,7 @@ from app.scodoc.sco_exceptions import ScoValueError
|
|||||||
from app.scodoc.TrivialFormulator import TrivialFormulator
|
from app.scodoc.TrivialFormulator import TrivialFormulator
|
||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_cal
|
from app.scodoc import sco_cal
|
||||||
|
from app.scodoc import sco_assiduites as scass
|
||||||
from app.scodoc import sco_abs_billets
|
from app.scodoc import sco_abs_billets
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
@ -312,54 +313,16 @@ def _ProcessBilletAbsence(
|
|||||||
n = 0 # nombre de demi-journées d'absence ajoutées
|
n = 0 # nombre de demi-journées d'absence ajoutées
|
||||||
|
|
||||||
# 1-- Ajout des absences (et justifs)
|
# 1-- Ajout des absences (et justifs)
|
||||||
datedebut = billet.abs_begin.strftime("%d/%m/%Y")
|
datedebut = billet.abs_begin
|
||||||
datefin = billet.abs_end.strftime("%d/%m/%Y")
|
datefin = billet.abs_end
|
||||||
dates = sco_cal.DateRangeISO(datedebut, datefin)
|
log(f"Gestion du billet n°{billet.id}")
|
||||||
# commence après-midi ?
|
n = scass.create_absence(
|
||||||
if dates and billet.abs_begin.hour > 11:
|
date_debut=datedebut,
|
||||||
# XXX TODO-ASSIDUITE
|
date_fin=datefin,
|
||||||
raise ScoValueError("Fonction non disponible")
|
etudid=billet.etudid,
|
||||||
sco_abs.add_absence(
|
description=description,
|
||||||
billet.etudid,
|
est_just=estjust,
|
||||||
dates[0],
|
)
|
||||||
0,
|
|
||||||
estjust,
|
|
||||||
description=description,
|
|
||||||
)
|
|
||||||
n += 1
|
|
||||||
dates = dates[1:]
|
|
||||||
# termine matin ?
|
|
||||||
if dates and billet.abs_end.hour < 12:
|
|
||||||
# XXX TODO-ASSIDUITE
|
|
||||||
raise ScoValueError("Fonction non disponible")
|
|
||||||
sco_abs.add_absence(
|
|
||||||
billet.etudid,
|
|
||||||
dates[-1],
|
|
||||||
1,
|
|
||||||
estjust,
|
|
||||||
description=description,
|
|
||||||
)
|
|
||||||
n += 1
|
|
||||||
dates = dates[:-1]
|
|
||||||
|
|
||||||
for jour in dates:
|
|
||||||
raise ScoValueError("Fonction non disponible")
|
|
||||||
sco_abs.add_absence(
|
|
||||||
billet.etudid,
|
|
||||||
jour,
|
|
||||||
0,
|
|
||||||
estjust,
|
|
||||||
description=description,
|
|
||||||
)
|
|
||||||
# XXX TODO-ASSIDUITE
|
|
||||||
sco_abs.add_absence(
|
|
||||||
billet.etudid,
|
|
||||||
jour,
|
|
||||||
1,
|
|
||||||
estjust,
|
|
||||||
description=description,
|
|
||||||
)
|
|
||||||
n += 2
|
|
||||||
|
|
||||||
# 2- Change état du billet
|
# 2- Change état du billet
|
||||||
billet.etat = True
|
billet.etat = True
|
||||||
|
@ -1002,7 +1002,9 @@ def signal_assiduites_diff():
|
|||||||
"assiduites/pages/signal_assiduites_diff.j2",
|
"assiduites/pages/signal_assiduites_diff.j2",
|
||||||
diff=_differee(
|
diff=_differee(
|
||||||
etudiants=etudiants,
|
etudiants=etudiants,
|
||||||
moduleimpl_select=_module_selector(formsemestre),
|
moduleimpl_select=_module_selector(
|
||||||
|
formsemestre, request.args.get("moduleimpl_id", None)
|
||||||
|
),
|
||||||
date=date,
|
date=date,
|
||||||
periode={
|
periode={
|
||||||
"deb": formsemestre.date_debut.isoformat(),
|
"deb": formsemestre.date_debut.isoformat(),
|
||||||
@ -1162,6 +1164,11 @@ def _module_selector(
|
|||||||
)
|
)
|
||||||
modules.append({"moduleimpl_id": modimpl["moduleimpl_id"], "name": modname})
|
modules.append({"moduleimpl_id": modimpl["moduleimpl_id"], "name": modname})
|
||||||
|
|
||||||
|
try:
|
||||||
|
moduleimpl_id = int(moduleimpl_id)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
moduleimpl_id = None
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"assiduites/widgets/moduleimpl_selector.j2",
|
"assiduites/widgets/moduleimpl_selector.j2",
|
||||||
selected=selected,
|
selected=selected,
|
||||||
|
Loading…
Reference in New Issue
Block a user