forked from ScoDoc/ScoDoc
214 lines
7.2 KiB
Python
214 lines
7.2 KiB
Python
##############################################################################
|
|
# ScoDoc
|
|
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
|
|
# See LICENSE
|
|
##############################################################################
|
|
|
|
"""
|
|
API : itemsuivi devenir/débouché des étudiants
|
|
|
|
CATEGORY
|
|
--------
|
|
Étudiants
|
|
"""
|
|
import datetime
|
|
|
|
from flask import g, request, Response
|
|
from flask_json import as_json
|
|
from flask_login import login_required
|
|
|
|
from app.api import api_bp as bp, api_web_bp
|
|
from app.api import api_permission_required as permission_required
|
|
from app import db, log
|
|
from app.decorators import scodoc
|
|
from app.models import Identite, ItemSuivi, ItemSuiviTag, Scolog
|
|
from app.scodoc import sco_permissions_check
|
|
from app.scodoc.sco_permissions import Permission
|
|
from app.scodoc.sco_exceptions import AccessDenied
|
|
import app.scodoc.sco_utils as scu
|
|
|
|
|
|
@bp.post("/etudiant/<int:etudid>/itemsuivi/create")
|
|
@api_web_bp.post("/etudiant/<int:etudid>/itemsuivi/create")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.EtudChangeAdr)
|
|
@as_json
|
|
def itemsuivi_create(etudid):
|
|
"""Création d'un item de suivi associé à l'étudiant.
|
|
|
|
The form MAY contain:
|
|
- item_date: date of the item
|
|
- situation: text
|
|
"""
|
|
if not sco_permissions_check.can_edit_suivi():
|
|
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
|
etud = Identite.get_etud(etudid)
|
|
ok, item_date = _get_date_from_form()
|
|
item_date = item_date if ok else datetime.datetime.now()
|
|
situation = request.form.get("situation") or ""
|
|
item = ItemSuivi(etudid=etudid, item_date=item_date, situation=situation)
|
|
db.session.add(item)
|
|
db.session.commit()
|
|
Scolog.logdb(method="itemsuivi_create", etudid=etud.id, commit=True)
|
|
log(f"itemsuivi_create {item} for {etud}")
|
|
db.session.refresh(item)
|
|
return item.to_dict(merge_tags=True)
|
|
|
|
|
|
@bp.post("/etudiant/itemsuivi/<int:itemid>/delete")
|
|
@api_web_bp.post("/etudiant/itemsuivi/<int:itemid>/delete")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.EtudChangeAdr)
|
|
@as_json
|
|
def itemsuivi_suppress(itemid):
|
|
"""Suppression d'un item"""
|
|
if not sco_permissions_check.can_edit_suivi():
|
|
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
|
item: ItemSuivi = ItemSuivi.get_instance(itemid, accept_none=True)
|
|
if item is None:
|
|
return {"status": "ok", "message": "item not found"}
|
|
etudid = item.etudid
|
|
db.session.delete(item)
|
|
db.session.commit()
|
|
Scolog.logdb(method="itemsuivi_suppress", etudid=etudid, commit=True)
|
|
log(f"itemsuivi_suppress: itemid={itemid}")
|
|
return {"status": "ok", "message": "item deleted"}
|
|
|
|
|
|
@bp.get("/etudiant/<int:etudid>/itemsuivis")
|
|
@api_web_bp.get("/etudiant/<int:etudid>/itemsuivis")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def itemsuivi_list_etud(etudid: int):
|
|
"""Liste des items pour cet étudiant, avec tags"""
|
|
etud = Identite.get_etud(etudid)
|
|
items = [it.to_dict(merge_tags=True) for it in etud.itemsuivis]
|
|
return items
|
|
|
|
|
|
@bp.post("/etudiant/itemsuivi/<int:itemid>/tag")
|
|
@api_web_bp.post("/etudiant/itemsuivi/<int:itemid>/tag")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.EtudChangeAdr)
|
|
@as_json
|
|
def itemsuivi_tag_set(itemid: int):
|
|
"""
|
|
taglist a string with tag names separated by commas e.g.: `un,deux`
|
|
"""
|
|
if not sco_permissions_check.can_edit_suivi():
|
|
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
|
item: ItemSuivi = ItemSuivi.get_instance(itemid)
|
|
taglist_str = request.form.get("taglist")[: scu.MAX_TEXT_LEN]
|
|
if taglist_str is None:
|
|
return scu.json_error(400, "missing taglist in form")
|
|
taglist = [t.strip() for t in taglist_str.split(",")]
|
|
item.set_tags(taglist)
|
|
db.session.add(item)
|
|
db.session.commit()
|
|
log(f"itemsuivi_tag_set: itemsuivi_id={item.id} taglist={taglist}")
|
|
return item.to_dict(merge_tags=True)
|
|
|
|
|
|
@bp.post("/etudiant/itemsuivi/<int:itemid>/set_situation")
|
|
@api_web_bp.post("/etudiant/itemsuivi/<int:itemid>/set_situation")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.EtudChangeAdr)
|
|
def itemsuivi_set_situation(itemid: int):
|
|
"""Modifie le champ situation de l'item de suivi de l'étudiant.
|
|
|
|
Form data: "value" : "situation ..."
|
|
|
|
Appel utilisé par champ éditable sur fiche étudiant.
|
|
"""
|
|
if not sco_permissions_check.can_edit_suivi():
|
|
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
|
item: ItemSuivi = ItemSuivi.get_instance(itemid)
|
|
if "value" not in request.form:
|
|
return scu.json_error(400, "missing value in form")
|
|
situation = request.form["value"]
|
|
item.situation = situation.strip("-_ \t\r\n")[: scu.MAX_TEXT_LEN]
|
|
db.session.add(item)
|
|
db.session.commit()
|
|
log(f"itemsuivi_set_situation: itemid={itemid} situation={item.situation[:32]}")
|
|
return item.situation or scu.IT_SITUATION_MISSING_STR
|
|
|
|
|
|
@bp.post("/etudiant/itemsuivi/<int:itemid>/set_date")
|
|
@api_web_bp.post("/etudiant/itemsuivi/<int:itemid>/set_date")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.EtudChangeAdr)
|
|
@as_json
|
|
def itemsuivi_set_date(itemid: int):
|
|
"""set item date
|
|
|
|
Specify date as an ISO date string
|
|
or date_dmy, string dd/mm/yyyy
|
|
"""
|
|
if not sco_permissions_check.can_edit_suivi():
|
|
raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !")
|
|
ok, date_or_resp = _get_date_from_form()
|
|
if not ok:
|
|
return date_or_resp
|
|
item: ItemSuivi = ItemSuivi.get_instance(itemid)
|
|
item.item_date = date_or_resp
|
|
db.session.add(item)
|
|
db.session.commit()
|
|
log(f"itemsuivi_set_date: itemid={itemid} date={item.item_date}")
|
|
return item.to_dict(merge_tags=True)
|
|
|
|
|
|
def _get_date_from_form() -> tuple[bool, datetime.datetime | Response]:
|
|
"""get date from form
|
|
Specify date as an ISO date string
|
|
or date_dmy, string dd/mm/yyyy
|
|
"""
|
|
date_iso = request.form.get("date") # ISO format
|
|
if date_iso:
|
|
try:
|
|
return True, datetime.datetime.fromisoformat(date_iso)
|
|
except ValueError:
|
|
return False, scu.json_error(400, "invalide date format (iso)")
|
|
date_dmy = request.form.get("date_dmy")
|
|
if not date_dmy:
|
|
return False, scu.json_error(400, "missing date or date_dmy in form")
|
|
try:
|
|
return True, datetime.datetime.strptime(date_dmy, scu.DATE_FMT)
|
|
except ValueError:
|
|
return False, scu.json_error(400, "invalide date format (jj/mm/aaaa)")
|
|
|
|
|
|
@bp.get("/etudiant/itemsuivi/tags/search")
|
|
@api_web_bp.get("/etudiant/itemsuivi/tags/search")
|
|
@login_required
|
|
@scodoc
|
|
@permission_required(Permission.ScoView)
|
|
@as_json
|
|
def itemsuivi_tag_search():
|
|
"""List all used tag names (for auto-completion)
|
|
|
|
Query: term
|
|
"""
|
|
if getattr(g, "scodoc_dept_id", None) is None:
|
|
return [] # accès départemental seulement
|
|
term = request.args.get("term", "").strip()[: scu.MAX_TEXT_LEN]
|
|
# restrict charset to avoid injections
|
|
if not scu.ALPHANUM_EXP.match(term):
|
|
data = []
|
|
else:
|
|
data = [
|
|
x.title
|
|
for x in ItemSuiviTag.query.filter(
|
|
ItemSuiviTag.title.like(f"{term}%"),
|
|
ItemSuiviTag.dept_id == g.scodoc_dept_id,
|
|
).all()
|
|
]
|
|
|
|
return data
|