############################################################################## # 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//itemsuivi/create") @api_web_bp.post("/etudiant//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//delete") @api_web_bp.post("/etudiant/itemsuivi//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//itemsuivis") @api_web_bp.get("/etudiant//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//tag") @api_web_bp.post("/etudiant/itemsuivi//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//set_situation") @api_web_bp.post("/etudiant/itemsuivi//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//set_date") @api_web_bp.post("/etudiant/itemsuivi//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