forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -6,18 +6,18 @@
|
|||||||
"""ScoDoc 9 API : Assiduités
|
"""ScoDoc 9 API : Assiduités
|
||||||
"""
|
"""
|
||||||
from datetime import datetime
|
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_assiduites as scass
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app import db
|
|
||||||
from app.api import api_bp as bp
|
from app.api import api_bp as bp
|
||||||
from app.api import api_web_bp
|
from app.api import api_web_bp, get_model_api_object
|
||||||
from app.api import get_model_api_object
|
|
||||||
from app.decorators import permission_required, scodoc
|
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_exceptions import ScoValueError
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
from app.scodoc.sco_utils import json_error
|
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()
|
assiduite_unique: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first()
|
||||||
if assiduite_unique is None:
|
if assiduite_unique is None:
|
||||||
return (404, "Assiduite non existante")
|
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)
|
database.session.delete(assiduite_unique)
|
||||||
|
scass.simple_invalidate_cache(ass_dict)
|
||||||
return (200, "OK")
|
return (200, "OK")
|
||||||
|
|
||||||
|
|
||||||
@ -630,6 +637,12 @@ def assiduite_edit(assiduite_id: int):
|
|||||||
err: str = ", ".join(errors)
|
err: str = ", ".join(errors)
|
||||||
return json_error(404, err)
|
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.add(assiduite_unique)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
scass.simple_invalidate_cache(assiduite_unique.to_dict())
|
scass.simple_invalidate_cache(assiduite_unique.to_dict())
|
||||||
@ -645,14 +658,17 @@ def assiduite_edit(assiduite_id: int):
|
|||||||
@permission_required(Permission.ScoAbsChange)
|
@permission_required(Permission.ScoAbsChange)
|
||||||
def assiduites_edit():
|
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":
|
La requête doit avoir un content type "application/json":
|
||||||
|
[
|
||||||
{
|
{
|
||||||
|
"assiduite_id" : int,
|
||||||
"etat"?: str,
|
"etat"?: str,
|
||||||
"moduleimpl_id"?: int
|
"moduleimpl_id"?: int
|
||||||
"desc"?: str
|
"desc"?: str
|
||||||
"est_just"?: bool
|
"est_just"?: bool
|
||||||
}
|
}
|
||||||
|
]
|
||||||
"""
|
"""
|
||||||
edit_list: list[object] = request.get_json(force=True)
|
edit_list: list[object] = request.get_json(force=True)
|
||||||
|
|
||||||
@ -664,7 +680,7 @@ def assiduites_edit():
|
|||||||
for i, data in enumerate(edit_list):
|
for i, data in enumerate(edit_list):
|
||||||
assi: Identite = Assiduite.query.filter_by(id=data["assiduite_id"]).first()
|
assi: Identite = Assiduite.query.filter_by(id=data["assiduite_id"]).first()
|
||||||
if assi is None:
|
if assi is None:
|
||||||
errors[i] = "Cet assiduité n'existe pas."
|
errors[i] = f"assiduité {data['assiduite_id']} n'existe pas."
|
||||||
continue
|
continue
|
||||||
|
|
||||||
code, obj = _edit_singular(assi, data)
|
code, obj = _edit_singular(assi, data)
|
||||||
@ -727,6 +743,12 @@ def _edit_singular(assiduite_unique, data):
|
|||||||
err: str = ", ".join(errors)
|
err: str = ", ".join(errors)
|
||||||
return (404, err)
|
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)
|
db.session.add(assiduite_unique)
|
||||||
scass.simple_invalidate_cache(assiduite_unique.to_dict())
|
scass.simple_invalidate_cache(assiduite_unique.to_dict())
|
||||||
|
|
||||||
|
@ -3,16 +3,10 @@
|
|||||||
"""
|
"""
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from app import db
|
from app import db, log
|
||||||
from app.models import ModuleImpl
|
from app.models import ModuleImpl, Scolog
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.auth.models import User
|
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_exceptions import ScoValueError
|
||||||
from app.scodoc.sco_utils import (
|
from app.scodoc.sco_utils import (
|
||||||
EtatAssiduite,
|
EtatAssiduite,
|
||||||
@ -92,6 +86,20 @@ class Assiduite(db.Model):
|
|||||||
}
|
}
|
||||||
return data
|
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
|
@classmethod
|
||||||
def create_assiduite(
|
def create_assiduite(
|
||||||
cls,
|
cls,
|
||||||
@ -140,33 +148,12 @@ class Assiduite(db.Model):
|
|||||||
est_just=est_just,
|
est_just=est_just,
|
||||||
)
|
)
|
||||||
|
|
||||||
return nouv_assiduite
|
log(f"create_assiduite: {nouv_assiduite}")
|
||||||
|
Scolog.logdb(
|
||||||
@classmethod
|
method="create_assiduite",
|
||||||
def fast_create_assiduite(
|
etudid=etud.id,
|
||||||
cls,
|
msg=f"assiduité: {nouv_assiduite}",
|
||||||
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,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return nouv_assiduite
|
return nouv_assiduite
|
||||||
|
|
||||||
|
|
||||||
@ -266,29 +253,6 @@ class Justificatif(db.Model):
|
|||||||
)
|
)
|
||||||
return nouv_justificatif
|
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(
|
def is_period_conflicting(
|
||||||
date_debut: datetime,
|
date_debut: datetime,
|
||||||
|
@ -93,7 +93,7 @@ _formsemestreEditor = ndb.EditableTable(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_formsemestre(formsemestre_id: int):
|
def get_formsemestre(formsemestre_id: int) -> dict:
|
||||||
"list ONE formsemestre"
|
"list ONE formsemestre"
|
||||||
if formsemestre_id is None:
|
if formsemestre_id is None:
|
||||||
raise ValueError("get_formsemestre: id manquant")
|
raise ValueError("get_formsemestre: id manquant")
|
||||||
|
@ -1608,12 +1608,12 @@ function deleteJustificatif(justif_id) {
|
|||||||
function errorAlert() {
|
function errorAlert() {
|
||||||
const html = `
|
const html = `
|
||||||
<h3>Avez vous les droits suffisant pour cette action ?</h3>
|
<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>
|
<br>
|
||||||
<p><i>pour les développeurs : l'erreur est affichée dans la console JS</i></p>
|
<p><i>pour les développeurs : l'erreur est affichée dans la console JS</i></p>
|
||||||
|
|
||||||
`;
|
`;
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.innerHTML = html;
|
div.innerHTML = html;
|
||||||
openAlertModal("Une erreur s'est déclanchée", div);
|
openAlertModal("Une erreur s'est produite", div);
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,12 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from flask import g, url_for
|
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
|
from app.tables import table_builder as tb
|
||||||
import app.scodoc.sco_assiduites as scass
|
import app.scodoc.sco_assiduites as scass
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
|
from app.scodoc import sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
class TableAssi(tb.Table):
|
class TableAssi(tb.Table):
|
||||||
@ -23,12 +25,13 @@ class TableAssi(tb.Table):
|
|||||||
self,
|
self,
|
||||||
etuds: list[Identite] = None,
|
etuds: list[Identite] = None,
|
||||||
dates: tuple[str, str] = None,
|
dates: tuple[str, str] = None,
|
||||||
|
formsemestre: FormSemestre = None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
self.rows: list["RowEtud"] = [] # juste pour que VSCode nous aide sur .rows
|
self.rows: list["RowEtud"] = [] # juste pour que VSCode nous aide sur .rows
|
||||||
classes = ["gt_table", "gt_left"]
|
classes = ["gt_table", "gt_left"]
|
||||||
self.dates = [str(dates[0]) + "T00:00", str(dates[1]) + "T23:59"]
|
self.dates = [str(dates[0]) + "T00:00", str(dates[1]) + "T23:59"]
|
||||||
|
self.formsemestre = formsemestre
|
||||||
super().__init__(
|
super().__init__(
|
||||||
row_class=RowAssi,
|
row_class=RowAssi,
|
||||||
classes=classes,
|
classes=classes,
|
||||||
@ -50,6 +53,17 @@ class RowAssi(tb.Row):
|
|||||||
|
|
||||||
# pour le moment très simple, extensible (codes, liens bulletins, ...)
|
# pour le moment très simple, extensible (codes, liens bulletins, ...)
|
||||||
def __init__(self, table: TableAssi, etud: Identite, *args, **kwargs):
|
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)
|
super().__init__(table, etud.id, *args, **kwargs)
|
||||||
self.etud = etud
|
self.etud = etud
|
||||||
self.dates = table.dates
|
self.dates = table.dates
|
||||||
|
@ -4,6 +4,7 @@ from flask import g, request, render_template
|
|||||||
|
|
||||||
from flask import abort, url_for
|
from flask import abort, url_for
|
||||||
|
|
||||||
|
from app import db
|
||||||
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 (
|
||||||
@ -669,9 +670,11 @@ def visu_assi_group():
|
|||||||
map(str, group_ids)
|
map(str, group_ids)
|
||||||
|
|
||||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(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])
|
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"):
|
if fmt.startswith("xls"):
|
||||||
return scu.send_file(
|
return scu.send_file(
|
||||||
|
@ -121,15 +121,6 @@ class _Merger:
|
|||||||
"entry_date": self.entry_date,
|
"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):
|
def _to_assi(self):
|
||||||
date_deb = _Merger._tuple_to_date(self.deb)
|
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):
|
def export(self):
|
||||||
"""Génère un nouvel objet Assiduité ou Justificatif"""
|
"""Génère un nouvel objet Assiduité ou Justificatif"""
|
||||||
obj: Assiduite or Justificatif = None
|
obj: Assiduite or Justificatif = None
|
||||||
|
Loading…
Reference in New Issue
Block a user