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
6 changed files with 81 additions and 27 deletions
Showing only changes of commit 152fca5748 - Show all commits

View File

@ -532,7 +532,7 @@ def assiduite_create(etudid: int = None, nip=None, ine=None):
# On créé l'assiduité # On créé l'assiduité
# 200 + obj si réussi # 200 + obj si réussi
# 404 + message d'erreur si non réussi # 404 + message d'erreur si non réussi
code, obj = create_one_assiduite(data, etud) code, obj = _create_one(data, etud)
if code == 404: if code == 404:
errors.append({"indice": i, "message": obj}) errors.append({"indice": i, "message": obj})
else: else:
@ -590,7 +590,7 @@ def assiduites_create():
# route sans département # route sans département
set_sco_dept(etud.departement.acronym) set_sco_dept(etud.departement.acronym)
code, obj = create_one_assiduite(data, etud) code, obj = _create_one(data, etud)
if code == 404: if code == 404:
errors.append({"indice": i, "message": obj}) errors.append({"indice": i, "message": obj})
else: else:
@ -600,14 +600,14 @@ def assiduites_create():
return {"errors": errors, "success": success} return {"errors": errors, "success": success}
def create_one_assiduite( def _create_one(
data: dict, data: dict,
etud: Identite, etud: Identite,
) -> tuple[int, object]: ) -> tuple[int, object]:
""" """
create_one_assiduite: création d'une assiduité à partir d'un dict Création d'une assiduité à partir d'un dict
Cette fonction vérifie les données du dict (qui vient du JSON API ou d'ailleurs) Cette fonction vérifie les données du dict (qui vient du JSON API)
Puis crée l'assiduité si la représentation est valide. Puis crée l'assiduité si la représentation est valide.
@ -761,7 +761,7 @@ def assiduite_delete():
# Pour chaque assiduite_id on essaye de supprimer l'assiduité # Pour chaque assiduite_id on essaye de supprimer l'assiduité
for i, assiduite_id in enumerate(assiduites_list): for i, assiduite_id in enumerate(assiduites_list):
# De la même façon que "create_one_assiduite" # De la même façon que "_create_one"
# Ici le code est soit 200 si réussi ou 404 si raté # Ici le code est soit 200 si réussi ou 404 si raté
# Le message est le message d'erreur si erreur # Le message est le message d'erreur si erreur
code, msg = _delete_one(assiduite_id) code, msg = _delete_one(assiduite_id)

View File

@ -101,5 +101,14 @@ class AjoutAssiduiteEtudForm(FlaskForm):
"maxlength": 500, "maxlength": 500,
}, },
) )
entry_date = StringField(
"Date de dépot ou saisie",
validators=[validators.Length(max=10)],
render_kw={
"class": "datepicker",
"size": 10,
"id": "entry_date",
},
)
submit = SubmitField("Enregistrer") submit = SubmitField("Enregistrer")
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True}) cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})

View File

@ -135,7 +135,10 @@ class Assiduite(db.Model):
external_data: dict = None, external_data: dict = None,
notify_mail=False, notify_mail=False,
) -> "Assiduite": ) -> "Assiduite":
"""Créer une nouvelle assiduité pour l'étudiant""" """Créer une nouvelle assiduité pour l'étudiant.
Les datetime doivent être en timzone serveur.
Raises ScoValueError en cas de conflit ou erreur.
"""
if date_debut.tzinfo is None: if date_debut.tzinfo is None:
log( log(
f"Warning: create_assiduite: date_debut without timezone ({date_debut})" f"Warning: create_assiduite: date_debut without timezone ({date_debut})"

View File

@ -75,9 +75,10 @@ MAX_TEXT_LEN = 64 * 1024
STATIC_DIR = ( STATIC_DIR = (
os.environ.get("SCRIPT_NAME", "") + "/ScoDoc/static/links/" + sco_version.SCOVERSION os.environ.get("SCRIPT_NAME", "") + "/ScoDoc/static/links/" + sco_version.SCOVERSION
) )
# La time zone du serveur:
# Attention: suppose que la timezone utilisée par postgresql soit la même ! # Attention: suppose que la timezone utilisée par postgresql soit la même !
TIME_ZONE = timezone("/".join(os.path.realpath("/etc/localtime").split("/")[-2:])) TIME_ZONE = timezone("/".join(os.path.realpath("/etc/localtime").split("/")[-2:]))
"La timezone du serveur"
# ----- CIVILITE ETUDIANTS # ----- CIVILITE ETUDIANTS
CIVILITES = {"M": "M.", "F": "Mme", "X": ""} CIVILITES = {"M": "M.", "F": "Mme", "X": ""}
@ -252,7 +253,9 @@ def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or No
def localize_datetime(date: datetime.datetime or str) -> datetime.datetime: def localize_datetime(date: datetime.datetime or str) -> datetime.datetime:
"""Ajoute un timecode UTC à la date donnée.""" """Ajoute un timecode UTC à la date donnée.
XXX semble faire autre chose... TODO fix this comment
"""
if isinstance(date, str): if isinstance(date, str):
date = is_iso_formated(date, convert=True) date = is_iso_formated(date, convert=True)

View File

@ -41,6 +41,13 @@ div.radio-assi_etat input[type="radio"]:checked + label {
/* Style for checked state */ /* Style for checked state */
font-weight: bold; font-weight: bold;
} }
div.submit {
margin-top: 12px;
}
div.submit > input {
margin-right: 16px;
}
</style> </style>
<div class="tab-content"> <div class="tab-content">
@ -89,8 +96,12 @@ div.radio-assi_etat input[type="radio"]:checked + label {
{{ form.assi_raison() }} {{ form.assi_raison() }}
{{ render_field_errors(form, 'assi_raison') }} {{ render_field_errors(form, 'assi_raison') }}
</div> </div>
{# Date dépot #}
{{ form.entry_date.label }}&nbsp;: {{ form.entry_date }}
<span class="help">laisser vide pour date courante</span>
{{ render_field_errors(form, 'entry_date') }}
{# Submit #} {# Submit #}
<div> <div class="submit">
{{ form.submit }} {{ form.cancel }} {{ form.submit }} {{ form.cancel }}
</div> </div>
</form> </form>

View File

@ -32,7 +32,6 @@ from flask import abort, url_for, redirect, Response
from flask_login import current_user from flask_login import current_user
from app import db from app import db
from app.api.assiduites import create_one_assiduite
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.decorators import ( from app.decorators import (
@ -41,17 +40,18 @@ from app.decorators import (
) )
from app.forms.assiduite.ajout_assiduite_etud import AjoutAssiduiteEtudForm from app.forms.assiduite.ajout_assiduite_etud import AjoutAssiduiteEtudForm
from app.models import ( from app.models import (
FormSemestre,
Identite,
ScoDocSiteConfig,
Assiduite, Assiduite,
Justificatif,
Departement, Departement,
Evaluation, Evaluation,
FormSemestre,
Identite,
Justificatif,
ModuleImpl,
ScoDocSiteConfig,
) )
from app.scodoc.codes_cursus import UE_STANDARD from app.scodoc.codes_cursus import UE_STANDARD
from app.auth.models import User from app.auth.models import User
from app.models.assiduites import get_assiduites_justif, compute_assiduites_justified from app.models.assiduites import get_assiduites_justif
import app.tables.liste_assiduites as liste_assi import app.tables.liste_assiduites as liste_assi
from app.views import assiduites_bp as bp from app.views import assiduites_bp as bp
@ -396,6 +396,12 @@ def _record_assiduite_etud(
ok = False ok = False
else: else:
moduleimpl_id = None moduleimpl_id = None
# La date de dépot (si viden date actuelle)
dt_entry_date = (
datetime.datetime.strptime(form.entry_date.data, "%d/%m/%Y")
if form.entry_date.data
else None
)
if not ok: if not ok:
return False return False
# Vérifie cohérence des dates/heures # Vérifie cohérence des dates/heures
@ -404,18 +410,40 @@ def _record_assiduite_etud(
if dt_fin <= dt_debut: if dt_fin <= dt_debut:
form.errors["general_errors"] = ["Erreur: dates début/fin incohérentes"] form.errors["general_errors"] = ["Erreur: dates début/fin incohérentes"]
return False return False
data = { # Ajoute time zone serveur
"date_debut": dt_debut.isoformat(), dt_debut_tz_server = scu.TIME_ZONE.localize(dt_debut)
"date_fin": dt_fin.isoformat(), dt_fin_tz_server = scu.TIME_ZONE.localize(dt_fin)
"etat": form.assi_etat.data, dt_entry_date_tz_server = (
"moduleimpl_id": moduleimpl_id, scu.TIME_ZONE.localize(dt_entry_date) if dt_entry_date else None
} )
ok, result = create_one_assiduite(data, etud) external_data = None
if ok == 200: moduleimpl: ModuleImpl | None = None
# assiduite_id = result["assiduite_id"] match moduleimpl_id:
case "autre":
external_data = {"module": "Autre"}
case None:
moduleimpl = None
case _:
moduleimpl = ModuleImpl.query.get(moduleimpl_id)
try:
ass = Assiduite.create_assiduite(
etud,
dt_debut_tz_server,
dt_fin_tz_server,
scu.EtatAssiduite.get(form.assi_etat.data),
description=form.assi_raison.data,
entry_date=dt_entry_date_tz_server,
external_data=external_data,
moduleimpl=moduleimpl,
notify_mail=True,
user_id=current_user.id,
)
db.session.add(ass)
db.session.commit()
return True return True
form.errors["general_errors"] = [f"Erreur: {result}"] except ScoValueError as exc:
return False form.errors["general_errors"] = [f"Erreur: {exc.args[0]}"]
return False
# # Génération de la page # # Génération de la page
# return HTMLBuilder( # return HTMLBuilder(