Log etud: code & check

This commit is contained in:
Emmanuel Viennet 2024-07-08 23:13:45 +02:00
parent e230118c59
commit 34fe649d51
16 changed files with 91 additions and 166 deletions

View File

@ -290,13 +290,12 @@ def validation_rcue_record(etudid: int):
db.session.add(validation)
# invalider bulletins (les autres résultats ne dépendent pas des RCUEs):
sco_cache.invalidate_formsemestre_etud(etud)
db.session.commit()
Scolog.logdb(
method="validation_rcue_record",
etudid=etudid,
msg=f"Enregistrement {validation}",
commit=True,
)
db.session.commit()
log(f"{operation} {validation}")
return validation.to_dict()

View File

@ -533,13 +533,12 @@ def justif_edit(justif_id: int):
# Mise à jour du justificatif
justificatif_unique.dejustifier_assiduites()
db.session.add(justificatif_unique)
db.session.commit()
Scolog.logdb(
method="edit_justificatif",
etudid=justificatif_unique.etudiant.id,
msg=f"justificatif modif: {justificatif_unique}",
)
db.session.commit()
# Génération du dictionnaire de retour
# La couverture correspond
@ -627,6 +626,11 @@ def _delete_one(justif_id: int) -> tuple[int, str]:
scass.simple_invalidate_cache(justificatif_unique.to_dict())
# On actualise les assiduités justifiées de l'étudiant concerné
justificatif_unique.dejustifier_assiduites()
Scolog.logdb(
method="justificatif/delete",
etudid=justificatif_unique.etudiant.id,
msg="suppression justificatif",
)
# On supprime le justificatif
db.session.delete(justificatif_unique)

View File

@ -12,12 +12,12 @@ from app import db
from app import email
from app import log
from app.auth.models import User
from app.models import SHORT_STR_LEN
from app.models import ScoDocModel, SHORT_STR_LEN
import app.scodoc.sco_utils as scu
from app.scodoc import sco_preferences
class Scolog(db.Model):
class Scolog(ScoDocModel):
"""Log des actions (journal modif etudiants)"""
__tablename__ = "scolog"
@ -34,7 +34,8 @@ class Scolog(db.Model):
def logdb(
cls, method: str = None, etudid: int = None, msg: str = None, commit=False
):
"""Add entry in student's log (replacement for old scolog.logdb)"""
"""Add entry in student's log (replacement for old scolog.logdb).
Par défaut ne commite pas."""
entry = Scolog(
method=method,
msg=msg,
@ -45,6 +46,21 @@ class Scolog(db.Model):
if commit:
db.session.commit()
def to_dict(self, convert_date=False) -> dict:
"convert to dict"
return {
"etudid": self.etudid,
"date": (
(self.date.strftime(scu.DATETIME_FMT) if convert_date else self.date)
if self.date
else ""
),
"_date_order": self.date.isoformat() if self.date else "",
"authenticated_user": self.authenticated_user or "",
"msg": self.msg or "",
"method": self.method or "",
}
class ScolarNews(db.Model):
"""Nouvelles pour page d'accueil"""

View File

@ -31,13 +31,18 @@
from app import db
from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat
from app.models import FormSemestre, Identite, ScolarAutorisationInscription, UniteEns
from app.models import (
FormSemestre,
Identite,
ScolarAutorisationInscription,
Scolog,
UniteEns,
)
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app import log
from app.scodoc.scolog import logdb
from app.scodoc import sco_cache, sco_etud
from app.scodoc import sco_cache
from app.scodoc import sco_formsemestre
from app.scodoc.codes_cursus import (
CMP,
@ -586,13 +591,11 @@ class SituationEtudCursusClassic(SituationEtudCursus):
decision.assiduite,
decision.formsemestre_id_utilise_pour_compenser,
)
logdb(
cnx,
Scolog.logdb(
method="validate_sem",
etudid=self.etudid,
commit=False,
msg="formsemestre_id=%s code=%s"
% (self.formsemestre_id, decision.code_etat),
msg=f"formsemestre_id={self.formsemestre_id} code={decision.code_etat}",
)
# -- decisions UEs
formsemestre_validate_ues(
@ -616,13 +619,11 @@ class SituationEtudCursusClassic(SituationEtudCursus):
assidu=True,
formsemestre_id_utilise_pour_compenser=fsid,
)
logdb(
cnx,
Scolog.logdb(
method="validate_sem",
etudid=self.etudid,
commit=False,
msg="formsemestre_id=%s code=%s"
% (self.prev_formsemestre.id, decision.new_code_prev),
msg=f"formsemestre_id={self.prev_formsemestre.id} code={decision.new_code_prev}",
)
# modifs des codes d'UE (pourraient passer de ADM a CMP, meme sans modif des notes)
formsemestre_validate_ues(
@ -937,13 +938,13 @@ def formsemestre_validate_ues(formsemestre_id, etudid, code_etat_sem, assiduite)
cnx, nt, formsemestre_id, etudid, ue_id, code_ue
)
logdb(
cnx,
Scolog.logdb(
method="validate_ue",
etudid=etudid,
msg="ue_id=%s code=%s" % (ue_id, code_ue),
msg=f"ue_id={ue_id} code={code_ue}",
commit=False,
)
db.session.commit()
cnx.commit()

View File

@ -34,11 +34,10 @@ from flask import url_for, g, request
from app import log
from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat
from app.models import FormSemestre
from app.models import FormSemestre, Scolog
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
from app.scodoc.scolog import logdb
from app.scodoc.gen_tables import GenTable
from app.scodoc import safehtml
from app.scodoc import html_sco_header
@ -291,8 +290,8 @@ def itemsuivi_suppress(itemsuivi_id):
item = itemsuivi_get(cnx, itemsuivi_id, ignore_errors=True)
if item:
_itemsuivi_delete(cnx, itemsuivi_id)
logdb(cnx, method="itemsuivi_suppress", etudid=item["etudid"])
log("suppressed itemsuivi %s" % (itemsuivi_id,))
Scolog.logdb(method="itemsuivi_suppress", etudid=item["etudid"], commit=True)
log(f"suppressed itemsuivi {itemsuivi_id}")
return ("", 204)
@ -304,7 +303,7 @@ def itemsuivi_create(etudid, item_date=None, situation="", fmt=None):
itemsuivi_id = _itemsuivi_create(
cnx, args={"etudid": etudid, "item_date": item_date, "situation": situation}
)
logdb(cnx, method="itemsuivi_create", etudid=etudid)
Scolog.logdb(method="itemsuivi_create", etudid=etudid, commit=True)
log("created itemsuivi %s for %s" % (itemsuivi_id, etudid))
item = itemsuivi_get(cnx, itemsuivi_id)
if fmt == "json":

View File

@ -37,7 +37,7 @@ from flask import url_for, g
from app import db, email
from app import log
from app.models import Admission, Identite
from app.models import Admission, Identite, Scolog
from app.models.etudiants import (
check_etud_duplicate_code,
input_civilite,
@ -53,10 +53,9 @@ from app.scodoc.sco_utils import (
format_prenom,
)
import app.scodoc.notesdb as ndb
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc import safehtml
from app.scodoc import sco_preferences
from app.scodoc.scolog import logdb
def format_etud_ident(etud: dict):
@ -511,8 +510,7 @@ def create_etud(cnx, args: dict = None):
etudid = etud.id
# log
logdb(
cnx,
Scolog.logdb(
method="etudident_edit_form",
etudid=etudid,
msg="creation initiale",
@ -681,17 +679,6 @@ o.close()
"""
def list_scolog(etudid):
"liste des operations effectuees sur cet etudiant"
cnx = ndb.GetDBConnexion()
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
cursor.execute(
"SELECT * FROM scolog WHERE etudid=%(etudid)s ORDER BY DATE DESC",
{"etudid": etudid},
)
return cursor.dictfetchall()
def fill_etuds_info(etuds: list[dict], add_admission=True):
"""etuds est une liste d'etudiants (mappings)
Pour chaque etudiant, ajoute ou formatte les champs

View File

@ -42,7 +42,6 @@ from app.models.groups import Partition, GroupDescr
from app.models.scolar_event import ScolarEvent
import app.scodoc.sco_utils as scu
from app import log
from app.scodoc.scolog import logdb
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.codes_cursus import UE_STANDARD, UE_SPORT, UE_TYPE_NAME
import app.scodoc.notesdb as ndb
@ -112,12 +111,11 @@ def do_formsemestre_inscription_create(args, method=None):
},
)
# Log etudiant
logdb(
cnx,
Scolog.logdb(
method=method,
etudid=args["etudid"],
msg=f"inscription en semestre {args['formsemestre_id']}",
commit=False,
commit=True,
)
#
sco_cache.invalidate_formsemestre(formsemestre_id=args["formsemestre_id"])
@ -265,12 +263,11 @@ def do_formsemestre_desinscription(
db.session.commit()
flash(f"Semestre extérieur supprimé: {formsemestre.titre_annee()}")
logdb(
cnx,
Scolog.logdb(
method="formsemestre_desinscription",
etudid=etudid,
msg=f"desinscription semestre {formsemestre_id}",
commit=False,
commit=True,
)

View File

@ -41,7 +41,7 @@ from app import db, log
from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat
from app.models import Formation, FormSemestre, UniteEns, ScolarNews
from app.models import Formation, FormSemestre, UniteEns, ScolarNews, Scolog
from app.models.notes import etud_has_notes_attente
from app.models.validations import (
ScolarAutorisationInscription,
@ -49,7 +49,6 @@ from app.models.validations import (
)
from app.models.but_validations import ApcValidationRCUE, ApcValidationAnnee
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.scolog import logdb
from app.scodoc.codes_cursus import *
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
@ -1077,7 +1076,7 @@ def do_formsemestre_validation_auto(formsemestre_id):
url_for('notes.formsemestre_validation_etud_form',
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id,
etudid=etud.id, check=1)
}">{etud_d["nomprenom"]}</li>"""
}">{etud.nom_prenom()}</li>"""
)
H.append("</ul>")
H.append(
@ -1392,12 +1391,11 @@ def do_formsemestre_validate_previous_ue(
is_external=True,
)
logdb(
cnx,
Scolog.logdb(
method="formsemestre_validate_previous_ue",
etudid=etudid,
msg=f"Validation UE prec. {ue_id} {ue.acronyme}: {code}",
commit=False,
commit=True,
)
_invalidate_etud_formation_caches(etudid, formsemestre.formation_id)
cnx.commit()

View File

@ -44,9 +44,7 @@ from app.comp.res_compat import NotesTableCompat
from app.models import FormSemestre, Identite, Scolog
from app.models import SHORT_STR_LEN
from app.models.groups import GroupDescr, Partition
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.scolog import logdb
from app.scodoc import html_sco_header
from app.scodoc import sco_cache
from app.scodoc import codes_cursus
@ -769,12 +767,12 @@ groupsToDelete={groupsToDelete}
{"etudid": etudid, "group_id": group_id},
cursor=cursor,
)
logdb(
cnx,
Scolog.logdb(
method="removeFromGroup",
etudid=etudid,
msg=f"""formsemestre_id={partition.formsemestre.id},partition_name={
partition.partition_name}, group_name={group.group_name}""",
commit=True,
)
# Supprime les groupes indiqués comme supprimés:

View File

@ -30,7 +30,7 @@
import psycopg2
from app.scodoc import scolog
from app.models import Scolog
from app.scodoc import sco_cache
import app.scodoc.notesdb as ndb
from app.scodoc.sco_exceptions import ScoValueError
@ -182,12 +182,11 @@ def do_moduleimpl_inscription_create(args, formsemestre_id=None, cnx=None):
sco_cache.invalidate_formsemestre(
formsemestre_id=formsemestre_id
) # > moduleimpl_inscription
scolog.logdb(
cnx,
Scolog.logdb(
method="moduleimpl_inscription",
etudid=args["etudid"],
msg=f"inscription module {args['moduleimpl_id']}",
commit=False,
commit=True,
)
return r

View File

@ -44,8 +44,8 @@ from app.models import (
Partition,
ScolarFormSemestreValidation,
UniteEns,
Scolog,
)
from app.scodoc.scolog import logdb
from app.scodoc import html_sco_header
from app.scodoc import htmlutils
from app.scodoc import sco_cache
@ -774,12 +774,11 @@ def do_etud_desinscrit_ue_classic(etudid, formsemestre_id, ue_id):
""",
{"etudid": etudid, "formsemestre_id": formsemestre_id, "ue_id": ue_id},
)
logdb(
cnx,
Scolog.logdb(
method="etud_desinscrit_ue",
etudid=etudid,
msg=f"desinscription UE {ue_id}",
commit=False,
commit=True,
)
sco_cache.invalidate_formsemestre(
formsemestre_id=formsemestre_id

View File

@ -800,7 +800,7 @@ def menus_etud(etudid):
},
{
"title": "Voir le journal...",
"endpoint": "scolar.showEtudLog",
"endpoint": "scolar.show_etud_log",
"args": {"etudid": etud["etudid"]},
"enabled": True,
},

View File

@ -64,8 +64,6 @@ from app.scodoc import sco_etud
from app.scodoc import sco_portal_apogee
from app.scodoc import sco_preferences
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc.scolog import logdb
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
from config import Config
@ -304,10 +302,9 @@ def suppress_photo(etud: Identite) -> None:
for filename in filenames:
log(f"removing file {filename}")
os.remove(filename)
db.session.commit()
# 3- log
cnx = ndb.GetDBConnexion()
logdb(cnx, method="changePhoto", msg="suppression", etudid=etud.id)
Scolog.logdb(method="changePhoto", msg="suppression", etudid=etud.id)
db.session.commit()
# ---------------------------------------------------------------------------

View File

@ -1,68 +0,0 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
"""Logging des opérations en base de données
"""
from flask import request
from flask_login import current_user
import app.scodoc.notesdb as ndb
def logdb(cnx=None, method=None, etudid=None, msg=None, commit=True):
"Add entry"
if not cnx:
raise ValueError("logdb: cnx is None")
args = {
"authenticated_user": current_user.user_name,
}
args.update({"method": method, "etudid": etudid, "msg": msg})
ndb.quote_dict(args)
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
cursor.execute(
"""INSERT INTO scolog
(authenticated_user,method,etudid,msg)
VALUES
(%(authenticated_user)s,%(method)s,%(etudid)s,%(msg)s)""",
args,
)
if commit:
cnx.commit()
def loglist(cnx, method=None, authenticated_user=None):
"""List of events logged for these method and user"""
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
cursor.execute(
"""SELECT * FROM scolog
WHERE method=%(method)s
AND authenticated_user=%(authenticated_user)s""",
{"method": method, "authenticated_user": authenticated_user},
)
return cursor.dictfetchall()

View File

@ -2909,7 +2909,7 @@ def formsemestre_saisie_jury(formsemestre_id: int, selected_etudid: int = None):
@scodoc
@permission_required(Permission.ScoView)
def formsemestre_jury_erase(formsemestre_id: int, etudid: int = None):
"""Supprime la décision de jury (classique ou BUT) pour cette année.
"""Supprime toutes les décisions de jury (classique ou BUT) pour cette année.
Si l'étudiant n'est pas spécifié, efface les décisions de tous les inscrits.
En BUT, si only_one_sem n'efface que pour le formsemestre indiqué, pas les deux de l'année.
En classique, n'affecte que les décisions issues de ce formsemestre.
@ -2992,8 +2992,10 @@ def formsemestre_jury_erase(formsemestre_id: int, etudid: int = None):
"""
+ """
<p>Efface aussi toutes les validations concernant l'année BUT de ce semestre,
même si elles ont été acquises ailleurs.
</p>"""
même si elles ont été acquises ailleurs, ainsi que les validations de DUT en 120 ECTS
obtenues après BUT1/BUT2.
</p>
"""
if is_apc
else ""
+ """

View File

@ -70,7 +70,6 @@ from app.views import ScoData
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.scolog import logdb
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_exceptions import (
AccessDenied,
@ -78,7 +77,7 @@ from app.scodoc.sco_exceptions import (
ScoValueError,
)
from app.scodoc.TrivialFormulator import DMY_REGEXP, TrivialFormulator, tf_error_message
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
from app.scodoc.gen_tables import GenTable
from app.scodoc import (
codes_cursus,
@ -302,39 +301,37 @@ class DeptLogosConfigurationForm(FlaskForm):
# --------------------------------------------------------------------
@bp.route("/showEtudLog")
@bp.route("/show_etud_log")
@scodoc
@permission_required(Permission.ScoView)
@scodoc7func
def showEtudLog(etudid, fmt="html"):
def show_etud_log(etudid, fmt="html"):
"""Display log of operations on this student"""
etud = sco_etud.get_etud_info(filled=True)[0]
ops = sco_etud.list_scolog(etudid)
etud = Identite.get_etud(etudid)
operations = Scolog.query.filter_by(etudid=etud.id).order_by(Scolog.date.desc())
tab = GenTable(
titles={
"date": "Date",
"authenticated_user": "Utilisateur",
"remote_addr": "IP",
"method": "Opération",
"msg": "Message",
},
columns_ids=("date", "authenticated_user", "remote_addr", "method", "msg"),
rows=ops,
columns_ids=("date", "authenticated_user", "method", "msg"),
rows=[op.to_dict(convert_date=True) for op in operations],
html_sortable=True,
html_class="table_leftalign",
base_url="%s?etudid=%s" % (request.base_url, etudid),
page_title="Opérations sur %(nomprenom)s" % etud,
html_title="<h2>Opérations effectuées sur l'étudiant %(nomprenom)s</h2>" % etud,
filename="log_" + scu.make_filename(etud["nomprenom"]),
base_url="%s?etudid=%s" % (request.base_url, etud.id),
page_title=f"Opérations sur {etud.nom_prenom()}",
html_title=f"""<h2>Opérations effectuées sur l'étudiant{etud.e} {
etud.html_link_fiche()}</h2>""",
filename="log_" + scu.make_filename(etud.nom_prenom()),
html_next_section=f"""
<ul><li>
<a href="{url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)}">
fiche de {etud['nomprenom']}</a></li>
<ul>
<li>Fiche de {etud.html_link_fiche()}</li>
</ul>""",
preferences=sco_preferences.SemPreferences(),
table_id="showEtudLog",
table_id="show_etud_log",
)
return tab.make_page(fmt=fmt)
@ -738,7 +735,7 @@ def doAddAnnotation(etudid, comment):
"author": current_user.user_name,
},
)
logdb(cnx, method="addAnnotation", etudid=etudid)
Scolog.logdb(method="addAnnotation", etudid=etudid, commit=True)
return flask.redirect(
url_for("scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etudid)
)
@ -758,8 +755,8 @@ def doSuppressAnnotation(etudid, annotation_id):
if len(annos) != 1:
raise ScoValueError("annotation inexistante !")
anno = annos[0]
log("suppress annotation: %s" % str(anno))
logdb(cnx, method="SuppressAnnotation", etudid=etudid)
log(f"suppress annotation: {anno}")
Scolog.logdb(method="SuppressAnnotation", etudid=etudid)
sco_etud.etud_annotations_delete(cnx, annotation_id)
flash("Annotation supprimée")
@ -842,7 +839,7 @@ def form_change_coordonnees(etudid):
sco_etud.adresse_edit(cnx, args=tf[2])
else:
sco_etud.adresse_create(cnx, args=tf[2])
logdb(cnx, method="changeCoordonnees", etudid=etudid)
Scolog.logdb(method="changeCoordonnees", etudid=etudid, commit=True)
return flask.redirect(dest_url)