2024-11-04 21:26:18 +01:00
|
|
|
##############################################################################
|
|
|
|
# ScoDoc
|
|
|
|
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
|
|
|
|
# See LICENSE
|
|
|
|
##############################################################################
|
|
|
|
|
|
|
|
"""
|
|
|
|
ScoDoc 9 API : liste opérations effectuées par un utilisateur
|
|
|
|
|
|
|
|
CATEGORY
|
|
|
|
--------
|
|
|
|
Operations
|
|
|
|
"""
|
|
|
|
|
|
|
|
from flask import url_for
|
|
|
|
from flask_json import as_json
|
|
|
|
from flask_login import login_required
|
|
|
|
|
|
|
|
import app
|
|
|
|
from app import db
|
|
|
|
from app.api import api_bp as bp, api_web_bp
|
|
|
|
from app.api import api_permission_required as permission_required
|
|
|
|
from app.decorators import scodoc
|
|
|
|
from app.models import NotesNotes
|
|
|
|
from app.scodoc.sco_permissions import Permission
|
|
|
|
from app.scodoc import sco_utils as scu
|
|
|
|
|
|
|
|
MAX_QUERY_LENGTH = 10000
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route("/operations/user/<int:uid>/notes")
|
|
|
|
@api_web_bp.route("/operations/user/<int:uid>/notes")
|
|
|
|
@login_required
|
|
|
|
@scodoc
|
|
|
|
@permission_required(Permission.ScoView)
|
|
|
|
@as_json
|
|
|
|
def operations_user_notes(uid: int):
|
|
|
|
"""Liste les opérations de saisie de notes effectuées par utilisateur.
|
|
|
|
|
|
|
|
QUERY
|
|
|
|
-----
|
|
|
|
start: indice de début de la liste
|
|
|
|
length: nombre d'éléments à retourner
|
|
|
|
draw: numéro de la requête (pour pagination, renvoyé tel quel)
|
|
|
|
order[dir]: desc ou asc
|
|
|
|
search[value]: chaîne à chercher (dans évaluation et étudiant)
|
|
|
|
PARAMS
|
|
|
|
-----
|
|
|
|
uid: l'id de l'utilisateur
|
|
|
|
"""
|
2024-11-05 09:19:27 +01:00
|
|
|
# --- Permission: restreint au superadmin ou à l'utilisateur lui-même
|
|
|
|
if not app.current_user.is_administrator() and app.current_user.id != uid:
|
|
|
|
return {"error": "Permission denied"}, 403
|
2024-11-04 21:26:18 +01:00
|
|
|
start = int(app.request.args.get("start", 0))
|
|
|
|
length = min(int(app.request.args.get("length", 10)), MAX_QUERY_LENGTH)
|
|
|
|
order = app.request.args.get("order[dir]", "desc")
|
|
|
|
draw = int(app.request.args.get("draw", 1))
|
|
|
|
search = app.request.args.get("search[value]", "")
|
|
|
|
query = db.session.query(NotesNotes).filter(NotesNotes.uid == uid)
|
|
|
|
if order == "asc":
|
|
|
|
query = query.order_by(NotesNotes.date.asc())
|
|
|
|
else:
|
|
|
|
query = query.order_by(NotesNotes.date.desc())
|
|
|
|
|
|
|
|
# Pour l'efficacité, limite si pas de recherche en python
|
|
|
|
limited_query = query.offset(start).limit(length) if not search else query
|
|
|
|
|
|
|
|
data = []
|
|
|
|
for note in limited_query:
|
|
|
|
obj = {
|
|
|
|
"date": note.date.isoformat(),
|
|
|
|
"date_dmy": note.date.strftime(scu.DATEATIME_FMT),
|
|
|
|
"operation": "Saisie de note",
|
|
|
|
"value": scu.fmt_note(note.value),
|
|
|
|
"id": note.id,
|
|
|
|
"uid": note.uid,
|
|
|
|
"etudiant": note.etudiant.to_dict_short(),
|
|
|
|
"etudiant_link": note.etudiant.html_link_fiche(),
|
|
|
|
"evaluation": note.evaluation.to_dict_api(),
|
|
|
|
"evaluation_link": f"""<a href="{
|
|
|
|
url_for('notes.evaluation_listenotes',
|
|
|
|
scodoc_dept=note.evaluation.moduleimpl.formsemestre.departement.acronym,
|
|
|
|
evaluation_id=note.evaluation_id)
|
|
|
|
}">{note.evaluation.descr()}</a>""",
|
|
|
|
}
|
|
|
|
if search:
|
|
|
|
search = search.lower()
|
|
|
|
if (
|
|
|
|
search not in note.etudiant.nomprenom.lower()
|
|
|
|
and search not in note.evaluation.descr().lower()
|
|
|
|
and search not in obj["date_dmy"]
|
|
|
|
):
|
|
|
|
continue # skip
|
|
|
|
|
|
|
|
data.append(obj)
|
|
|
|
|
|
|
|
result = data[start : start + length] if search else data
|
|
|
|
return {
|
|
|
|
"draw": draw,
|
|
|
|
"recordsTotal": query.count(), # unfiltered
|
|
|
|
"recordsFiltered": len(data) if search else query.count(),
|
|
|
|
"data": result,
|
|
|
|
}
|