Merge branch 'master' of https://scodoc.org/git/viennet/ScoDoc into PNBUT

This commit is contained in:
Emmanuel Viennet 2021-11-03 16:25:48 +01:00
commit f534e9757f
6 changed files with 159 additions and 34 deletions

View File

@ -602,15 +602,15 @@ BOOL_STR = {
"false": False, "false": False,
"0": False, "0": False,
"1": True, "1": True,
"true": "true", "true": True,
} }
def bool_or_str(x): def bool_or_str(x) -> bool:
"""a boolean, may also be encoded as a string "0", "False", "1", "True" """ """a boolean, may also be encoded as a string "0", "False", "1", "True" """
if isinstance(x, str): if isinstance(x, str):
return BOOL_STR[x.lower()] return BOOL_STR[x.lower()]
return x return bool(x)
# post filtering # post filtering

View File

@ -790,7 +790,8 @@ def ListeAbsEtud(
absjust_only: si vrai, renvoie table absences justifiées absjust_only: si vrai, renvoie table absences justifiées
sco_year: année scolaire à utiliser. Si non spécifier, utilie l'année en cours. e.g. "2005" sco_year: année scolaire à utiliser. Si non spécifier, utilie l'année en cours. e.g. "2005"
""" """
absjust_only = int(absjust_only) # si vrai, table absjust seule (export xls ou pdf) # si absjust_only, table absjust seule (export xls ou pdf)
absjust_only = ndb.bool_or_str(absjust_only)
datedebut = "%s-08-01" % scu.AnneeScolaire(sco_year=sco_year) datedebut = "%s-08-01" % scu.AnneeScolaire(sco_year=sco_year)
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]

View File

@ -35,7 +35,7 @@ from flask import url_for, g, request
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.scodoc.scolog import logdb from app.scodoc.scolog import logdb
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoException, ScoValueError
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_codes_parcours import UE_STANDARD, UE_SPORT, UE_TYPE_NAME from app.scodoc.sco_codes_parcours import UE_STANDARD, UE_SPORT, UE_TYPE_NAME
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
@ -127,6 +127,42 @@ def do_formsemestre_inscription_delete(oid, formsemestre_id=None):
) # > desinscription du semestre ) # > desinscription du semestre
def do_formsemestre_demission(
etudid,
formsemestre_id,
event_date=None,
etat_new="D", # 'D' or DEF
operation_method="demEtudiant",
event_type="DEMISSION",
):
"Démission ou défaillance d'un étudiant"
# marque 'D' ou DEF dans l'inscription au semestre et ajoute
# un "evenement" scolarite
cnx = ndb.GetDBConnexion()
# check lock
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
if not sem["etat"]:
raise ScoValueError("Modification impossible: semestre verrouille")
#
ins = do_formsemestre_inscription_list(
{"etudid": etudid, "formsemestre_id": formsemestre_id}
)[0]
if not ins:
raise ScoException("etudiant non inscrit ?!")
ins["etat"] = etat_new
do_formsemestre_inscription_edit(args=ins, formsemestre_id=formsemestre_id)
logdb(cnx, method=operation_method, etudid=etudid)
sco_etud.scolar_events_create(
cnx,
args={
"etudid": etudid,
"event_date": event_date,
"formsemestre_id": formsemestre_id,
"event_type": event_type,
},
)
def do_formsemestre_inscription_edit(args=None, formsemestre_id=None): def do_formsemestre_inscription_edit(args=None, formsemestre_id=None):
"edit a formsemestre_inscription" "edit a formsemestre_inscription"
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()

View File

@ -360,6 +360,8 @@ def ue_set_internal(ue_id):
ue.is_external = False ue.is_external = False
db.session.add(ue) db.session.add(ue)
db.session.commit() db.session.commit()
# Invalide les semestres de cette formation
sco_edit_formation.invalidate_sems_in_formation(ue.formation_id)
return redirect( return redirect(
url_for( url_for(
"notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=ue.formation_id "notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=ue.formation_id

View File

@ -34,7 +34,7 @@ import os
import time import time
import flask import flask
from flask import jsonify, url_for, flash, redirect, render_template, make_response from flask import jsonify, url_for, flash, render_template, make_response
from flask import current_app, g, request from flask import current_app, g, request
from flask_login import current_user from flask_login import current_user
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
@ -215,7 +215,7 @@ def config_logos(scodoc_dept):
) )
app.clear_scodoc_cache() app.clear_scodoc_cache()
flash(f"Logos enregistrés") flash(f"Logos enregistrés")
return redirect(url_for("scolar.index_html", scodoc_dept=scodoc_dept)) return flask.redirect(url_for("scolar.index_html", scodoc_dept=scodoc_dept))
return render_template( return render_template(
"configuration.html", "configuration.html",
@ -1017,32 +1017,13 @@ def _do_dem_or_def_etud(
redirect=True, redirect=True,
): ):
"Démission ou défaillance d'un étudiant" "Démission ou défaillance d'un étudiant"
# marque 'D' ou DEF dans l'inscription au semestre et ajoute sco_formsemestre_inscriptions.do_formsemestre_demission(
# un "evenement" scolarite etudid,
cnx = ndb.GetDBConnexion() formsemestre_id,
# check lock event_date=event_date,
sem = sco_formsemestre.get_formsemestre(formsemestre_id) etat_new=etat_new, # 'D' or DEF
if not sem["etat"]: operation_method=operation_method,
raise ScoValueError("Modification impossible: semestre verrouille") event_type=event_type,
#
ins = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
{"etudid": etudid, "formsemestre_id": formsemestre_id}
)[0]
if not ins:
raise ScoException("etudiant non inscrit ?!")
ins["etat"] = etat_new
sco_formsemestre_inscriptions.do_formsemestre_inscription_edit(
args=ins, formsemestre_id=formsemestre_id
)
logdb(cnx, method=operation_method, etudid=etudid)
sco_etud.scolar_events_create(
cnx,
args={
"etudid": etudid,
"event_date": event_date,
"formsemestre_id": formsemestre_id,
"event_type": event_type,
},
) )
if redirect: if redirect:
return flask.redirect( return flask.redirect(

View File

@ -3,6 +3,7 @@
et aussi moyennes modules et UE internes (via nt) et aussi moyennes modules et UE internes (via nt)
""" """
from re import X
from config import TestConfig from config import TestConfig
from tests.unit import sco_fake_gen from tests.unit import sco_fake_gen
@ -11,8 +12,10 @@ from flask import g
import app import app
from app.scodoc import sco_bulletins from app.scodoc import sco_bulletins
from app.scodoc import sco_cache from app.scodoc import sco_cache
from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_moduleimpl from app.scodoc import sco_moduleimpl
from app.scodoc import sco_utils as scu from app.scodoc import sco_utils as scu
from app.views import scolar
DEPT = TestConfig.DEPT_TEST DEPT = TestConfig.DEPT_TEST
@ -40,6 +43,7 @@ def check_nt(
if expected_sum_coefs_ue is not False: if expected_sum_coefs_ue is not False:
ue_status = nt.get_etud_ue_status(etudid, ue_id) ue_status = nt.get_etud_ue_status(etudid, ue_id)
assert expected_sum_coefs_ue == ue_status["sum_coefs"] assert expected_sum_coefs_ue == ue_status["sum_coefs"]
return nt
def test_notes_modules(test_client): def test_notes_modules(test_client):
@ -149,7 +153,7 @@ def test_notes_modules(test_client):
moduleimpl_id, moduleimpl_id,
expected_mod_moy=0.0, expected_mod_moy=0.0,
expected_moy_ue=0.0, expected_moy_ue=0.0,
expected_sum_coefs_ue=0.0, expected_sum_coefs_ue=coef_mod_1, # absences, donc zéros et on garde le coef
) )
# Note excusée EXC <-> scu.NOTES_NEUTRALISE # Note excusée EXC <-> scu.NOTES_NEUTRALISE
@ -241,6 +245,7 @@ def test_notes_modules(test_client):
expected_sum_coefs_ue=0.0, expected_sum_coefs_ue=0.0,
) )
# --- Maintenant avec 2 modules dans l'UE # --- Maintenant avec 2 modules dans l'UE
coef_mod_2 = 2.1
mod2 = G.create_module( mod2 = G.create_module(
matiere_id=mat["matiere_id"], matiere_id=mat["matiere_id"],
code="TSM2", code="TSM2",
@ -305,3 +310,103 @@ def test_notes_modules(test_client):
) )
assert b2["ues"][0]["ue_status"]["cur_moy_ue"] == 11.0 assert b2["ues"][0]["ue_status"]["cur_moy_ue"] == 11.0
assert b2["ues"][0]["ue_status"]["moy"] == 11 assert b2["ues"][0]["ue_status"]["moy"] == 11
def test_notes_modules_att_dem(test_client):
"""Scénario dit "lyonnais":
Des étudiants, des notes, plusieurs étudiants avec notes ATT (ici notes éval en "attente"),
démission d'un étudiant qui avait ATT. Passage des autres ATT en EXC ou ABS.
On va tester avec un module, une éval, deux étudiants
"""
app.set_sco_dept(DEPT)
G = sco_fake_gen.ScoFake(verbose=False)
etuds = [G.create_etud(code_nip=None) for i in range(2)] # 2 étudiants
f = G.create_formation(acronyme="")
ue = G.create_ue(formation_id=f["formation_id"], acronyme="TST1", titre="ue test")
ue_id = ue["ue_id"]
mat = G.create_matiere(ue_id=ue_id, titre="matière test")
coef_mod_1 = 1.5
mod = G.create_module(
matiere_id=mat["matiere_id"],
code="TSM1",
coefficient=coef_mod_1,
titre="module test",
ue_id=ue["ue_id"],
formation_id=f["formation_id"],
)
#
# --------------------------------
#
sem = G.create_formsemestre(
formation_id=f["formation_id"],
semestre_id=1,
date_debut="01/01/2020",
date_fin="30/06/2020",
)
formsemestre_id = sem["formsemestre_id"]
mi = G.create_moduleimpl(
module_id=mod["module_id"],
formsemestre_id=formsemestre_id,
)
moduleimpl_id = mi["moduleimpl_id"]
# --- Inscription des étudiants
for etud in etuds:
G.inscrit_etudiant(sem, etud)
# --- Creation évaluation: e1
coef_1 = 1.0
e1 = G.create_evaluation(
moduleimpl_id=moduleimpl_id,
jour="01/01/2020",
description="evaluation 1",
coefficient=coef_1,
)
# Attente (ATT) sur les 2 evals
_, _, _ = G.create_note(evaluation=e1, etud=etuds[0], note=scu.NOTES_ATTENTE) # ATT
_, _, _ = G.create_note(evaluation=e1, etud=etuds[1], note=scu.NOTES_ATTENTE) # ATT
# Démission du premier étudiant
sco_formsemestre_inscriptions.do_formsemestre_demission(
etuds[0]["etudid"],
sem["formsemestre_id"],
event_date="02/01/2020",
)
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etuds[0]["etudid"]
)
assert b["etud_etat"] == "D"
assert b["nb_demissions"] == 1
assert b["ues"] == [] # inscrit à aucune UE !
# bulletin de l'étudiant non demissionnaire:
b = sco_bulletins.formsemestre_bulletinetud_dict(
sem["formsemestre_id"], etuds[1]["etudid"]
)
assert b["etud_etat"] == "I"
assert b["nb_demissions"] == 1
assert len(b["ues"]) == 1
nt = check_nt(
etuds[1]["etudid"],
sem["formsemestre_id"],
ue_id,
moduleimpl_id,
expected_mod_moy="NA0",
expected_moy_ue=0.0,
expected_sum_coefs_ue=0.0,
)
note_e1 = nt.get_etud_eval_note(etuds[1]["etudid"], e1["evaluation_id"])
assert note_e1["value"] == scu.NOTES_ATTENTE
note_e1 = nt.get_etud_eval_note(etuds[0]["etudid"], e1["evaluation_id"])
assert note_e1["value"] == scu.NOTES_ATTENTE # XXXX un peu contestable
# Saisie note ABS pour le deuxième etud
_, _, _ = G.create_note(evaluation=e1, etud=etuds[1], note=None) # ABS
nt = check_nt(
etuds[1]["etudid"],
sem["formsemestre_id"],
ue_id,
moduleimpl_id,
expected_mod_moy=0.0,
expected_moy_ue=0.0,
expected_sum_coefs_ue=coef_mod_1,
)
note_e1 = nt.get_etud_eval_note(etuds[1]["etudid"], e1["evaluation_id"])
assert note_e1["value"] is None