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
7 changed files with 83 additions and 100 deletions
Showing only changes of commit 740749e37e - Show all commits

View File

@ -6,18 +6,18 @@
"""ScoDoc 9 API : Assiduités
"""
from datetime import datetime
from flask_json import as_json
from flask import g, request
from flask_login import login_required, current_user
from flask import g, request
from flask_json import as_json
from flask_login import current_user, login_required
from app import db, log
import app.scodoc.sco_assiduites as scass
import app.scodoc.sco_utils as scu
from app import db
from app.api import api_bp as bp
from app.api import api_web_bp
from app.api import get_model_api_object
from app.api import api_web_bp, get_model_api_object
from app.decorators import permission_required, scodoc
from app.models import Assiduite, FormSemestre, Identite, ModuleImpl
from app.models import Assiduite, FormSemestre, Identite, ModuleImpl, Scolog
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_utils import json_error
@ -556,8 +556,15 @@ def _delete_singular(assiduite_id: int, database):
assiduite_unique: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first()
if assiduite_unique is None:
return (404, "Assiduite non existante")
scass.simple_invalidate_cache(assiduite_unique.to_dict())
ass_dict = assiduite_unique.to_dict()
log(f"delete_assiduite: {assiduite_unique}")
Scolog.logdb(
method="delete_assiduite",
etudid=assiduite_unique.etudiant.id,
msg=f"assiduité: {assiduite_unique}",
)
database.session.delete(assiduite_unique)
scass.simple_invalidate_cache(ass_dict)
return (200, "OK")
@ -630,6 +637,12 @@ def assiduite_edit(assiduite_id: int):
err: str = ", ".join(errors)
return json_error(404, err)
log(f"assiduite_edit: {assiduite_unique}")
Scolog.logdb(
"assiduite_edit",
assiduite_unique.etudiant.id,
msg=f"assiduite: modif {assiduite_unique}",
)
db.session.add(assiduite_unique)
db.session.commit()
scass.simple_invalidate_cache(assiduite_unique.to_dict())
@ -645,14 +658,17 @@ def assiduite_edit(assiduite_id: int):
@permission_required(Permission.ScoAbsChange)
def assiduites_edit():
"""
Edition d'une assiduité à partir de son id
Edition de plusieurs assiduités
La requête doit avoir un content type "application/json":
{
"etat"?: str,
"moduleimpl_id"?: int
"desc"?: str
"est_just"?: bool
}
[
{
"assiduite_id" : int,
"etat"?: str,
"moduleimpl_id"?: int
"desc"?: str
"est_just"?: bool
}
]
"""
edit_list: list[object] = request.get_json(force=True)
@ -664,7 +680,7 @@ def assiduites_edit():
for i, data in enumerate(edit_list):
assi: Identite = Assiduite.query.filter_by(id=data["assiduite_id"]).first()
if assi is None:
errors[i] = "Cet assiduité n'existe pas."
errors[i] = f"assiduité {data['assiduite_id']} n'existe pas."
continue
code, obj = _edit_singular(assi, data)
@ -727,6 +743,12 @@ def _edit_singular(assiduite_unique, data):
err: str = ", ".join(errors)
return (404, err)
log(f"_edit_singular: {assiduite_unique}")
Scolog.logdb(
"assiduite_edit",
assiduite_unique.etudiant.id,
msg=f"assiduite: modif {assiduite_unique}",
)
db.session.add(assiduite_unique)
scass.simple_invalidate_cache(assiduite_unique.to_dict())

View File

@ -3,16 +3,10 @@
"""
from datetime import datetime
from app import db
from app.models import ModuleImpl
from app import db, log
from app.models import ModuleImpl, Scolog
from app.models.etudiants import Identite
from app.auth.models import User
from app.scodoc.sco_utils import (
EtatAssiduite,
EtatJustificatif,
localize_datetime,
is_period_overlapping,
)
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.sco_utils import (
EtatAssiduite,
@ -92,6 +86,20 @@ class Assiduite(db.Model):
}
return data
def __str__(self) -> str:
"chaine pour journaux et debug (lisible par humain français)"
try:
etat_str = EtatAssiduite(self.etat).name.lower().capitalize()
except ValueError:
etat_str = "Invalide"
return f"""{etat_str} {
"just." if self.est_just else "non just."
} de {
self.date_debut.strftime("%d/%m/%Y %Hh%M")
} à {
self.date_fin.strftime("%d/%m/%Y %Hh%M")
}"""
@classmethod
def create_assiduite(
cls,
@ -140,33 +148,12 @@ class Assiduite(db.Model):
est_just=est_just,
)
return nouv_assiduite
@classmethod
def fast_create_assiduite(
cls,
etudid: int,
date_debut: datetime,
date_fin: datetime,
etat: EtatAssiduite,
moduleimpl_id: int = None,
description: str = None,
entry_date: datetime = None,
est_just: bool = False,
) -> object or int:
"""Créer une nouvelle assiduité pour l'étudiant"""
# Vérification de non duplication des périodes
nouv_assiduite = Assiduite(
date_debut=date_debut,
date_fin=date_fin,
etat=etat,
etudid=etudid,
moduleimpl_id=moduleimpl_id,
description=description,
entry_date=entry_date,
est_just=est_just,
log(f"create_assiduite: {nouv_assiduite}")
Scolog.logdb(
method="create_assiduite",
etudid=etud.id,
msg=f"assiduité: {nouv_assiduite}",
)
return nouv_assiduite
@ -266,29 +253,6 @@ class Justificatif(db.Model):
)
return nouv_justificatif
@classmethod
def fast_create_justificatif(
cls,
etudid: int,
date_debut: datetime,
date_fin: datetime,
etat: EtatJustificatif,
raison: str = None,
entry_date: datetime = None,
) -> object or int:
"""Créer un nouveau justificatif pour l'étudiant"""
nouv_justificatif = Justificatif(
date_debut=date_debut,
date_fin=date_fin,
etat=etat,
etudid=etudid,
raison=raison,
entry_date=entry_date,
)
return nouv_justificatif
def is_period_conflicting(
date_debut: datetime,

View File

@ -93,7 +93,7 @@ _formsemestreEditor = ndb.EditableTable(
)
def get_formsemestre(formsemestre_id: int):
def get_formsemestre(formsemestre_id: int) -> dict:
"list ONE formsemestre"
if formsemestre_id is None:
raise ValueError("get_formsemestre: id manquant")

View File

@ -1608,12 +1608,12 @@ function deleteJustificatif(justif_id) {
function errorAlert() {
const html = `
<h3>Avez vous les droits suffisant pour cette action ?</h3>
<p>Si c'est bien le cas : veuillez de l'aide sur le canal Assistance de ScoDoc</p>
<p>Si c'est bien le cas : demandez de l'aide sur le canal Assistance de ScoDoc</p>
<br>
<p><i>pour les développeurs : l'erreur est affichée dans la console JS</i></p>
`;
const div = document.createElement("div");
div.innerHTML = html;
openAlertModal("Une erreur s'est déclanchée", div);
openAlertModal("Une erreur s'est produite", div);
}

View File

@ -8,10 +8,12 @@
"""
from flask import g, url_for
from app.models import Identite, Justificatif
from app import log
from app.models import FormSemestre, Identite, Justificatif
from app.tables import table_builder as tb
import app.scodoc.sco_assiduites as scass
from app.scodoc import sco_preferences
from app.scodoc import sco_utils as scu
class TableAssi(tb.Table):
@ -23,12 +25,13 @@ class TableAssi(tb.Table):
self,
etuds: list[Identite] = None,
dates: tuple[str, str] = None,
formsemestre: FormSemestre = None,
**kwargs,
):
self.rows: list["RowEtud"] = [] # juste pour que VSCode nous aide sur .rows
classes = ["gt_table", "gt_left"]
self.dates = [str(dates[0]) + "T00:00", str(dates[1]) + "T23:59"]
self.formsemestre = formsemestre
super().__init__(
row_class=RowAssi,
classes=classes,
@ -50,6 +53,17 @@ class RowAssi(tb.Row):
# pour le moment très simple, extensible (codes, liens bulletins, ...)
def __init__(self, table: TableAssi, etud: Identite, *args, **kwargs):
# Etat de l'inscription au formsemestre
if "classes" not in kwargs:
kwargs["classes"] = []
try:
inscription = table.formsemestre.etuds_inscriptions[etud.id]
if inscription.etat == scu.DEMISSION:
kwargs["classes"].append("etuddem")
except KeyError:
log(f"RowAssi: etudid {etud.id} non inscrit à {table.formsemestre.id}")
kwargs["classes"].append("non_inscrit") # ne devrait pas arriver !
super().__init__(table, etud.id, *args, **kwargs)
self.etud = etud
self.dates = table.dates

View File

@ -4,6 +4,7 @@ from flask import g, request, render_template
from flask import abort, url_for
from app import db
from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat
from app.decorators import (
@ -669,9 +670,11 @@ def visu_assi_group():
map(str, group_ids)
groups_infos = sco_groups_view.DisplayedGroupsInfos(group_ids)
formsemestre = db.session.get(FormSemestre, groups_infos.formsemestre_id)
etuds = etuds_sorted_from_ids([m["etudid"] for m in groups_infos.members])
table: TableAssi = TableAssi(etuds=etuds, dates=list(dates.values()))
table: TableAssi = TableAssi(
etuds=etuds, dates=list(dates.values()), formsemestre=formsemestre
)
if fmt.startswith("xls"):
return scu.send_file(

View File

@ -121,15 +121,6 @@ class _Merger:
"entry_date": self.entry_date,
},
)
# retour = Justificatif.fast_create_justificatif(
# etudid=self.etudid,
# date_debut=date_deb,
# date_fin=date_fin,
# etat=EtatJustificatif.VALIDE,
# raison=self.raison,
# entry_date=self.entry_date,
# )
# return retour
def _to_assi(self):
date_deb = _Merger._tuple_to_date(self.deb)
@ -161,17 +152,6 @@ class _Merger:
},
)
# retour = Assiduite.fast_create_assiduite(
# etudid=self.etudid,
# date_debut=date_deb,
# date_fin=date_fin,
# etat=EtatAssiduite.ABSENT,
# moduleimpl_id=self.moduleimpl,
# description=self.raison,
# entry_date=self.entry_date,
# )
# return retour
def export(self):
"""Génère un nouvel objet Assiduité ou Justificatif"""
obj: Assiduite or Justificatif = None