Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
5 changed files with 100 additions and 117 deletions
Showing only changes of commit ca12519f1c - Show all commits

View File

@ -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:

View File

@ -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):

View File

@ -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>
""" """
) )

View File

@ -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

View File

@ -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,