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,
"0": False,
"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" """
if isinstance(x, str):
return BOOL_STR[x.lower()]
return x
return bool(x)
# post filtering

View File

@ -790,7 +790,8 @@ def ListeAbsEtud(
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"
"""
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)
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
from app import log
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_codes_parcours import UE_STANDARD, UE_SPORT, UE_TYPE_NAME
import app.scodoc.notesdb as ndb
@ -127,6 +127,42 @@ def do_formsemestre_inscription_delete(oid, formsemestre_id=None):
) # > 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):
"edit a formsemestre_inscription"
cnx = ndb.GetDBConnexion()

View File

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

View File

@ -34,7 +34,7 @@ import os
import time
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_login import current_user
from flask_wtf import FlaskForm
@ -215,7 +215,7 @@ def config_logos(scodoc_dept):
)
app.clear_scodoc_cache()
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(
"configuration.html",
@ -1017,32 +1017,13 @@ def _do_dem_or_def_etud(
redirect=True,
):
"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 = 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,
},
sco_formsemestre_inscriptions.do_formsemestre_demission(
etudid,
formsemestre_id,
event_date=event_date,
etat_new=etat_new, # 'D' or DEF
operation_method=operation_method,
event_type=event_type,
)
if redirect:
return flask.redirect(

View File

@ -3,6 +3,7 @@
et aussi moyennes modules et UE internes (via nt)
"""
from re import X
from config import TestConfig
from tests.unit import sco_fake_gen
@ -11,8 +12,10 @@ from flask import g
import app
from app.scodoc import sco_bulletins
from app.scodoc import sco_cache
from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_moduleimpl
from app.scodoc import sco_utils as scu
from app.views import scolar
DEPT = TestConfig.DEPT_TEST
@ -40,6 +43,7 @@ def check_nt(
if expected_sum_coefs_ue is not False:
ue_status = nt.get_etud_ue_status(etudid, ue_id)
assert expected_sum_coefs_ue == ue_status["sum_coefs"]
return nt
def test_notes_modules(test_client):
@ -149,7 +153,7 @@ def test_notes_modules(test_client):
moduleimpl_id,
expected_mod_moy=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
@ -241,6 +245,7 @@ def test_notes_modules(test_client):
expected_sum_coefs_ue=0.0,
)
# --- Maintenant avec 2 modules dans l'UE
coef_mod_2 = 2.1
mod2 = G.create_module(
matiere_id=mat["matiere_id"],
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"]["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