Bools. Edit formsemestre ok.

This commit is contained in:
Emmanuel Viennet 2021-08-11 00:36:07 +02:00
parent 4a43e96fe9
commit 055dcfea36
33 changed files with 223 additions and 166 deletions

View File

@ -9,6 +9,7 @@ import json
import os
import re
from time import time
from typing import Optional
from flask import current_app, url_for, g
from flask_login import UserMixin, AnonymousUserMixin
@ -265,12 +266,16 @@ class User(UserMixin, db.Model):
)
@staticmethod
def get_user_name_from_nomplogin(nomplogin):
"""Returns user_name from the string "Dupont Pierre (dupont)" """
def get_user_id_from_nomplogin(nomplogin: str) -> Optional[int]:
"""Returns id from the string "Dupont Pierre (dupont)"
or None if user does not exist
"""
m = re.match(r".*\((.*)\)", nomplogin.strip())
if m:
return m.group(1)
else:
user_name = m.group(1)
u = User.query.filter_by(user_name=user_name).first()
if u:
return u.id
return None
def get_nom_fmt(self):

View File

@ -199,7 +199,7 @@ def scodoc7func(context):
# necessary for db ids and boolean values
try:
v = int(v)
except ValueError:
except (ValueError, TypeError):
pass
kwargs[arg_name] = v
# current_app.logger.info(

View File

@ -287,9 +287,9 @@ class NotesEvaluation(db.Model):
publish_incomplete = db.Column(
db.Boolean, nullable=False, default=False, server_default="false"
)
# type d'evaluation: False normale, True rattrapage:
# type d'evaluation: 0 normale, 1 rattrapage, 2 "2eme session"
evaluation_type = db.Column(
db.Boolean, nullable=False, default=False, server_default="false"
db.Integer, nullable=False, default=0, server_default="0"
)
# ordre de presentation (par défaut, le plus petit numero
# est la plus ancienne eval):

View File

@ -209,7 +209,10 @@ class TF(object):
# convert numbers, except ids
if field.endswith("id") and self.values[field]:
# enforce integer ids:
try:
self.values[field] = int(self.values[field])
except ValueError:
pass
elif isinstance(self.values[field], (int, float)):
self.values[field] = str(self.values[field])
#
@ -299,9 +302,9 @@ class TF(object):
# boolean checkbox
if descr.get("input_type", None) == "boolcheckbox":
if int(val):
self.values[field] = 1
self.values[field] = True
else:
self.values[field] = 0
self.values[field] = False
# open('/tmp/toto','a').write('checkvalues: val=%s (%s) values[%s] = %s\n' % (val, type(val), field, self.values[field]))
if descr.get("convert_numbers", False):
if typ[:3] == "int":
@ -493,10 +496,15 @@ class TF(object):
checked = ""
else: # boolcheckbox
# open('/tmp/toto','a').write('GenForm: values[%s] = %s (%s)\n' % (field, values[field], type(values[field])))
if values[field] == "True":
v = True
elif values[field] == "False":
v = False
else:
try:
v = int(values[field])
except:
v = 0
v = False
if v:
checked = 'checked="checked"'
else:
@ -562,7 +570,7 @@ class TF(object):
'<input type="text" name="%s" id="%s" size="%d" %s'
% (field, field, size, attribs)
)
lem.append('value="%(' + field + ')s" />' % values)
lem.append(('value="%(' + field + ')s" />') % values)
suggest_js.append(
f"""var {field}_opts = {dict2js(descr.get("text_suggest_options", {}))};
var {field}_as = new bsn.AutoSuggest('{field}', {field}_opts);

View File

@ -800,7 +800,7 @@ class NotesTable(object):
# was_capitalized s'il y a precedemment une UE capitalisée (pas forcement meilleure)
mu["was_capitalized"] = False
is_external = 0
is_external = False
event_date = None
if not block_computation:
for ue_cap in self.ue_capitalisees[etudid]:
@ -1098,7 +1098,7 @@ class NotesTable(object):
if self.get_etud_etat(etudid) == DEF:
return {
"code": DEF,
"assidu": 0,
"assidu": False,
"event_date": "",
"compense_formsemestre_id": None,
}

View File

@ -764,6 +764,10 @@ _billet_absenceEditor = ndb.EditableTable(
"justified",
),
sortkey="entry_date desc",
input_formators={
"etat": bool,
"justified": bool,
},
)
billet_absence_create = _billet_absenceEditor.create

View File

@ -514,7 +514,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
mod["evaluations"] = []
for e in evals:
e = e.copy()
if int(e["visibulletin"]) == 1 or version == "long":
if e["visibulletin"] or version == "long":
# affiche "bonus" quand les points de malus sont négatifs
if is_malus:
val = e["notes"].get(etudid, {"value": "NP"})[

View File

@ -94,7 +94,7 @@ def formsemestre_bulletinetud_published_dict(
d = {}
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
if sem["bul_hide_xml"] == "0" or force_publishing:
if (not sem["bul_hide_xml"]) or force_publishing:
published = 1
else:
published = 0
@ -264,7 +264,7 @@ def formsemestre_bulletinetud_published_dict(
m["evaluation"] = []
if version != "short":
for e in evals:
if int(e["visibulletin"]) == 1 or version == "long":
if e["visibulletin"] or version == "long":
val = e["notes"].get(etudid, {"value": "NP"})[
"value"
] # NA si etud demissionnaire

View File

@ -155,7 +155,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
if self.version != "short":
# --- notes de chaque eval:
for e in mod["evaluations"]:
if int(e["visibulletin"]) == 1 or self.version == "long":
if e["visibulletin"] or self.version == "long":
H.append(
'<tr class="notes_bulletin_row_eval%s">' % rowstyle
)
@ -492,7 +492,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
if version != "short":
# --- notes de chaque eval:
for e in mod["evaluations"]:
if int(e["visibulletin"]) == 1 or version == "long":
if e["visibulletin"] or version == "long":
S.newline(ue_type=ue_type)
t = ["", "", e["name"], e["note_txt"], e["coef_txt"]]
if bul_show_abs_modules:

View File

@ -647,7 +647,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
# --- notes de chaque eval:
nbeval = 0
for e in evals:
if int(e["visibulletin"]) == 1 or self.version == "long":
if e["visibulletin"] or self.version == "long":
if nbeval == 0:
eval_style = " b_eval_first"
else:

View File

@ -82,7 +82,7 @@ def make_xml_formsemestre_bulletinetud(
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
if sem["bul_hide_xml"] == "0" or force_publishing:
if (not sem["bul_hide_xml"]) or force_publishing:
published = "1"
else:
published = "0"
@ -270,7 +270,7 @@ def make_xml_formsemestre_bulletinetud(
evals = nt.get_evals_in_mod(modimpl["moduleimpl_id"])
if version != "short":
for e in evals:
if int(e["visibulletin"]) == 1 or version == "long":
if e["visibulletin"] or version == "long":
x_eval = Element(
"evaluation",
jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True),

View File

@ -290,7 +290,7 @@ def do_moduleimpl_moyennes(context, nt, mod):
sum_coefs += e["coefficient"]
else:
# il manque une note ! (si publish_incomplete, cela peut arriver, on ignore)
if e["coefficient"] > 0 and e["publish_incomplete"] == "0":
if e["coefficient"] > 0 and not e["publish_incomplete"]:
nb_missing += 1
if nb_missing == 0 and sum_coefs > 0:
if sum_coefs > 0:

View File

@ -72,7 +72,10 @@ _ueEditor = ndb.EditableTable(
"coefficient",
),
sortkey="numero",
input_formators={"type": ndb.int_null_is_zero},
input_formators={
"type": ndb.int_null_is_zero,
"is_external": bool,
},
output_formators={
"numero": ndb.int_null_is_zero,
"ects": ndb.float_null_is_null,

View File

@ -149,7 +149,10 @@ _entreprisesEditor = EntreprisesEditor(
"date_creation",
),
sortkey="nom",
input_formators={"nom": _format_nom},
input_formators={
"nom": _format_nom,
"plus10salaries": bool,
},
)
# ----------- Correspondants

View File

@ -264,6 +264,7 @@ _identiteEditor = ndb.EditableTable(
"prenom": force_uppercase,
"civilite": input_civilite,
"date_naissance": ndb.DateDMYtoISO,
"boursier": bool,
},
output_formators={"date_naissance": ndb.DateISOtoDMY},
convert_null_outputs_to_empty=True,

View File

@ -115,8 +115,6 @@ _evaluationEditor = ndb.EditableTable(
sortkey="numero desc, jour desc, heure_debut desc", # plus recente d'abord
output_formators={
"jour": ndb.DateISOtoDMY,
"visibulletin": bool,
"publish_incomplete": bool,
"numero": ndb.int_null_is_zero,
},
input_formators={
@ -125,6 +123,7 @@ _evaluationEditor = ndb.EditableTable(
"heure_fin": ndb.TimetoISO8601, # converti par do_evaluation_list
"visibulletin": bool,
"publish_incomplete": bool,
"evaluation_type": int,
},
)
@ -494,14 +493,14 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
complete = True
if (
TotalNbMissing > 0
and (TotalNbMissing == TotalNbAtt or E["publish_incomplete"] != "0")
and ((TotalNbMissing == TotalNbAtt) or E["publish_incomplete"])
and not is_malus
):
evalattente = True
else:
evalattente = False
# mais ne met pas en attente les evals immediates sans aucune notes:
if E["publish_incomplete"] != "0" and nb_notes == 0:
if E["publish_incomplete"] and nb_notes == 0:
evalattente = False
# Calcul moyenne dans chaque groupe de TD
@ -1235,8 +1234,8 @@ def evaluation_create_form(
heures = ["%02dh%02d" % (h, m) for h in range(8, 19) for m in (0, 30)]
#
initvalues["visibulletin"] = initvalues.get("visibulletin", "1")
if initvalues["visibulletin"] == "1":
initvalues["visibulletin"] = initvalues.get("visibulletin", True)
if initvalues["visibulletin"]:
initvalues["visibulletinlist"] = ["X"]
else:
initvalues["visibulletinlist"] = []
@ -1372,9 +1371,9 @@ def evaluation_create_form(
else:
# form submission
if tf[2]["visibulletinlist"]:
tf[2]["visibulletin"] = 1
tf[2]["visibulletin"] = True
else:
tf[2]["visibulletin"] = 0
tf[2]["visibulletin"] = False
if not edit:
# creation d'une evaluation
evaluation_id = do_evaluation_create(REQUEST=REQUEST, **tf[2])

View File

@ -106,8 +106,13 @@ def search_etud_in_dept(context, expnom="", REQUEST=None):
expnom: string, regexp sur le nom ou un code_nip ou un etudid
"""
if len(expnom) > 1:
try:
etudid = int(expnom)
except ValueError:
etudid = None
if etudid is not None:
etuds = sco_etud.get_etud_info(filled=1, etudid=expnom, REQUEST=REQUEST)
if len(etuds) != 1:
if (etudid is None) or len(etuds) != 1:
if scu.is_valid_code_nip(expnom):
etuds = search_etuds_infos(code_nip=expnom)
else:

View File

@ -69,18 +69,19 @@ _formsemestreEditor = ndb.EditableTable(
output_formators={
"date_debut": ndb.DateISOtoDMY,
"date_fin": ndb.DateISOtoDMY,
"gestion_compensation": bool,
"gestion_semestrielle": bool,
"etat": bool,
"bul_hide_xml": bool,
},
input_formators={
"date_debut": ndb.DateDMYtoISO,
"date_fin": ndb.DateDMYtoISO,
"etat": bool,
"gestion_compensation": bool,
"bul_hide_xml": bool,
"gestion_semestrielle": bool,
"gestion_compensation": bool,
"gestion_semestrielle": bool,
"etat": bool,
"bul_hide_xml": bool,
"resp_can_edit": bool,
"resp_can_change_ens": bool,
"ens_can_edit_eval": bool,
},
)

View File

@ -29,6 +29,7 @@
"""
import flask
from flask import url_for, g
from flask_login import current_user
from app.auth.models import User
import app.scodoc.notesdb as ndb
@ -124,9 +125,8 @@ def formsemestre_editwithmodules(context, REQUEST, formsemestre_id):
def can_edit_sem(context, REQUEST, formsemestre_id="", sem=None):
"""Return sem if user can edit it, False otherwise"""
sem = sem or sco_formsemestre.get_formsemestre(context, formsemestre_id)
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(Permission.ScoImplement): # pas chef
if not sem["resp_can_edit"] or str(authuser) not in sem["responsables"]:
if not current_user.has_permission(Permission.ScoImplement): # pas chef
if not sem["resp_can_edit"] or current_user.id not in sem["responsables"]:
return False
return sem
@ -137,23 +137,22 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
if edit:
formsemestre_id = REQUEST.form["formsemestre_id"]
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(Permission.ScoImplement):
if not current_user.has_permission(Permission.ScoImplement):
if not edit:
# il faut ScoImplement pour creer un semestre
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
else:
if not sem["resp_can_edit"] or str(authuser) not in sem["responsables"]:
if not sem["resp_can_edit"] or current_user.id not in sem["responsables"]:
raise AccessDenied(
"vous n'avez pas le droit d'effectuer cette opération"
)
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
userlist = sco_users.get_user_list()
login2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
uid2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
for u in userlist:
login2display[u.user_name] = u.get_nomplogin()
allowed_user_names = list(login2display.values()) + [""]
uid2display[u.id] = u.get_nomplogin()
allowed_user_names = list(uid2display.values()) + [""]
#
formation_id = REQUEST.form["formation_id"]
F = sco_formations.formation_list(context, args={"formation_id": formation_id})
@ -168,29 +167,22 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
# setup form init values
initvalues = sem
semestre_id = initvalues["semestre_id"]
# initvalues['inscrire_etuds'] = initvalues.get('inscrire_etuds','1')
# if initvalues['inscrire_etuds'] == '1':
# initvalues['inscrire_etudslist'] = ['X']
# else:
# initvalues['inscrire_etudslist'] = []
# if REQUEST.form.get('tf-submitted',False) and not REQUEST.form.has_key('inscrire_etudslist'):
# REQUEST.form['inscrire_etudslist'] = []
# add associated modules to tf-checked
# add associated modules to tf-checked:
ams = sco_moduleimpl.do_moduleimpl_list(
context, formsemestre_id=formsemestre_id
)
sem_module_ids = set([x["module_id"] for x in ams])
initvalues["tf-checked"] = [x["module_id"] for x in ams]
initvalues["tf-checked"] = ["MI" + str(x["module_id"]) for x in ams]
for x in ams:
initvalues[str(x["module_id"])] = login2display.get(
initvalues["MI" + str(x["module_id"])] = uid2display.get(
x["responsable_id"], x["responsable_id"]
)
initvalues["responsable_id"] = login2display.get(
initvalues["responsable_id"] = uid2display.get(
sem["responsables"][0], sem["responsables"][0]
)
if len(sem["responsables"]) > 1:
initvalues["responsable_id2"] = login2display.get(
initvalues["responsable_id2"] = uid2display.get(
sem["responsables"][1], sem["responsables"][1]
)
@ -200,13 +192,13 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
NB_SEM = parcours.NB_SEM
else:
NB_SEM = 10 # fallback, max 10 semestres
semestre_id_list = ["-1"] + [str(x) for x in range(1, NB_SEM + 1)]
semestre_id_list = [-1] + list(range(1, NB_SEM + 1))
semestre_id_labels = []
for sid in semestre_id_list:
if sid == "-1":
semestre_id_labels.append("pas de semestres")
else:
semestre_id_labels.append(sid)
semestre_id_labels.append(str(sid))
# Liste des modules dans ce semestre de cette formation
# on pourrait faire un simple module_list( )
# mais si on veut l'ordre du PPN (groupe par UE et matieres) il faut:
@ -464,7 +456,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
},
),
]
if authuser.has_permission(Permission.ScoImplement):
if current_user.has_permission(Permission.ScoImplement):
modform += [
(
"resp_can_edit",
@ -627,8 +619,8 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
initvalues["vdi_apo" + str(n)] = etape_vdi.vdi
n += 1
#
initvalues["gestion_compensation"] = initvalues.get("gestion_compensation", "0")
if initvalues["gestion_compensation"] == "1":
initvalues["gestion_compensation"] = initvalues.get("gestion_compensation", False)
if initvalues["gestion_compensation"]:
initvalues["gestion_compensation_lst"] = ["X"]
else:
initvalues["gestion_compensation_lst"] = []
@ -638,8 +630,8 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
):
REQUEST.form["gestion_compensation_lst"] = []
initvalues["gestion_semestrielle"] = initvalues.get("gestion_semestrielle", "0")
if initvalues["gestion_semestrielle"] == "1":
initvalues["gestion_semestrielle"] = initvalues.get("gestion_semestrielle", False)
if initvalues["gestion_semestrielle"]:
initvalues["gestion_semestrielle_lst"] = ["X"]
else:
initvalues["gestion_semestrielle_lst"] = []
@ -649,8 +641,8 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
):
REQUEST.form["gestion_semestrielle_lst"] = []
initvalues["bul_hide_xml"] = initvalues.get("bul_hide_xml", "0")
if initvalues["bul_hide_xml"] == "0":
initvalues["bul_hide_xml"] = initvalues.get("bul_hide_xml", False)
if not initvalues["bul_hide_xml"]:
initvalues["bul_publish_xml_lst"] = ["X"]
else:
initvalues["bul_publish_xml_lst"] = []
@ -691,23 +683,23 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
return "<h4>annulation</h4>"
else:
if tf[2]["gestion_compensation_lst"]:
tf[2]["gestion_compensation"] = 1
tf[2]["gestion_compensation"] = True
else:
tf[2]["gestion_compensation"] = 0
tf[2]["gestion_compensation"] = False
if tf[2]["gestion_semestrielle_lst"]:
tf[2]["gestion_semestrielle"] = 1
tf[2]["gestion_semestrielle"] = True
else:
tf[2]["gestion_semestrielle"] = 0
tf[2]["gestion_semestrielle"] = False
if tf[2]["bul_publish_xml_lst"]:
tf[2]["bul_hide_xml"] = 0
tf[2]["bul_hide_xml"] = False
else:
tf[2]["bul_hide_xml"] = 1
tf[2]["bul_hide_xml"] = True
# remap les identifiants de responsables:
tf[2]["responsable_id"] = User.get_user_name_from_nomplogin(
tf[2]["responsable_id"] = User.get_user_id_from_nomplogin(
tf[2]["responsable_id"]
)
tf[2]["responsable_id2"] = User.get_user_name_from_nomplogin(
tf[2]["responsable_id2"] = User.get_user_id_from_nomplogin(
tf[2]["responsable_id2"]
)
tf[2]["responsables"] = [tf[2]["responsable_id"]]
@ -715,7 +707,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
tf[2]["responsables"].append(tf[2]["responsable_id2"])
for module_id in tf[2]["tf-checked"]:
mod_resp_id = User.get_user_name_from_nomplogin(tf[2][module_id])
mod_resp_id = User.get_user_id_from_nomplogin(tf[2][module_id])
if mod_resp_id is None:
# Si un module n'a pas de responsable (ou inconnu), l'affecte au 1er directeur des etudes:
mod_resp_id = tf[2]["responsable_id"]
@ -774,7 +766,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
modargs = {
"module_id": module_id,
"formsemestre_id": formsemestre_id,
"responsable_id": tf[2][module_id],
"responsable_id": tf[2]["MI" + str(module_id)],
}
moduleimpl_id = sco_moduleimpl.do_moduleimpl_create(context, modargs)
mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[
@ -825,7 +817,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
"moduleimpl_id": moduleimpl_id,
"module_id": module_id,
"formsemestre_id": formsemestre_id,
"responsable_id": tf[2][module_id],
"responsable_id": tf[2]["MI" + str(module_id)],
}
sco_moduleimpl.do_moduleimpl_edit(
context, modargs, formsemestre_id=formsemestre_id
@ -893,14 +885,14 @@ def formsemestre_clone(context, formsemestre_id, REQUEST=None):
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
userlist = sco_users.get_user_list()
login2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
uid2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
for u in userlist:
login2display[u.user_name] = u.get_nomplogin()
allowed_user_names = list(login2display.values()) + [""]
uid2display[u.id] = u.get_nomplogin()
allowed_user_names = list(uid2display.values()) + [""]
initvalues = {
"formsemestre_id": sem["formsemestre_id"],
"responsable_id": login2display.get(
"responsable_id": uid2display.get(
sem["responsables"][0], sem["responsables"][0]
),
}
@ -1001,7 +993,7 @@ def formsemestre_clone(context, formsemestre_id, REQUEST=None):
new_formsemestre_id = do_formsemestre_clone(
context,
formsemestre_id,
User.get_user_name_from_nomplogin(tf[2]["responsable_id"]),
User.get_user_id_from_nomplogin(tf[2]["responsable_id"]),
tf[2]["date_debut"],
tf[2]["date_fin"],
clone_evaluations=tf[2]["clone_evaluations"],
@ -1523,7 +1515,7 @@ def formsemestre_change_publication_bul(
if not ok:
return err
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
etat = 1 - int(sem["bul_hide_xml"])
etat = not sem["bul_hide_xml"]
if REQUEST and not dialog_confirmed:
if etat:
@ -1542,10 +1534,6 @@ def formsemestre_change_publication_bul(
parameters={"bul_hide_xml": etat, "formsemestre_id": formsemestre_id},
)
if etat not in (0, 1):
raise ScoValueError(
"formsemestre_change_publication_bul: invalid value for etat (%s)" % etat
)
args = {"formsemestre_id": formsemestre_id, "bul_hide_xml": etat}
sco_formsemestre.do_formsemestre_edit(context, args)
if REQUEST:

View File

@ -550,7 +550,7 @@ def fill_formsemestre(sem):
else:
sem["locklink"] = ""
if sco_preferences.get_preference("bul_display_publication", formsemestre_id):
if sem["bul_hide_xml"] != "0":
if sem["bul_hide_xml"]:
eyeicon = scu.icontag("hide_img", border="0", title="Bulletins NON publiés")
else:
eyeicon = scu.icontag("eye_img", border="0", title="Bulletins publiés")
@ -672,7 +672,7 @@ def formsemestre_description_table(
e["evalcomplete_str"] = "Non"
e["_evalcomplete_str_td_attrs"] = 'style="color: red;"'
if int(e["publish_incomplete"]):
if e["publish_incomplete"]:
e["publish_incomplete_str"] = "Oui"
e["_publish_incomplete_str_td_attrs"] = 'style="color: green;"'
else:
@ -969,7 +969,7 @@ Il y a des notes en attente ! Le classement des étudiants n'a qu'une valeur ind
</td></tr>"""
)
H.append("</table>")
if sem["bul_hide_xml"] != "0":
if sem["bul_hide_xml"]:
H.append(
'<p class="fontorange"><em>Bulletins non publiés sur le portail</em></p>'
)

View File

@ -323,7 +323,7 @@ def formsemestre_validation_etud_form(
)
H.append('<p style="font-size: 50%;">Formation ')
if Se.sem["gestion_semestrielle"] == "1":
if Se.sem["gestion_semestrielle"]:
H.append("avec semestres décalés</p>")
else:
H.append("sans semestres décalés</p>")
@ -375,7 +375,7 @@ def formsemestre_validation_etud_manu(
):
"""Enregistre validation"""
if assidu:
assidu = 1
assidu = True
etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0]
Se = sco_parcours_dut.SituationEtudParcours(context, etud, formsemestre_id)
if code_etat in Se.parcours.UNUSED_CODES:
@ -526,7 +526,7 @@ def formsemestre_recap_parcours_table(
pv = dpv["decisions"][0]
decision_sem = pv["decision_sem"]
decisions_ue = pv["decisions_ue"]
if with_all_columns and decision_sem and decision_sem["assidu"] == 0:
if with_all_columns and decision_sem and not decision_sem["assidu"]:
ass = " (non ass.)"
else:
ass = ""
@ -744,7 +744,7 @@ def form_decision_manuelle(
'<option value="%s">%s (code %s)</option>'
% (cod, sco_codes_parcours.CODES_EXPL[cod], cod)
)
elif Se.sem["gestion_compensation"] == "1":
elif Se.sem["gestion_compensation"]:
# traitement spécial pour ADC (compensation)
# ne propose que les semestres avec lesquels on peut compenser
# le code transmis est ADC_formsemestre_id
@ -795,7 +795,7 @@ def form_decision_manuelle(
else:
allowed_codes = set(sco_codes_parcours.DEVENIRS_STD)
# semestres decales ?
if Se.sem["gestion_semestrielle"] == "1":
if Se.sem["gestion_semestrielle"]:
allowed_codes = allowed_codes.union(sco_codes_parcours.DEVENIRS_DEC)
# n'autorise les codes NEXT2 que si semestres décalés et s'il ne manque qu'un semestre avant le n+2
if Se.can_jump_to_next2():
@ -1082,7 +1082,9 @@ def formsemestre_validate_previous_ue(context, formsemestre_id, etudid, REQUEST=
return "\n".join(H) + tf[1] + X + warn + html_sco_header.sco_footer()
elif tf[0] == -1:
return flask.redirect(
scu.NotesURL() + "/formsemestre_status?formsemestre_id=" + str(formsemestre_id)
scu.NotesURL()
+ "/formsemestre_status?formsemestre_id="
+ str(formsemestre_id)
)
else:
if tf[2]["semestre_id"]:
@ -1143,7 +1145,7 @@ def do_formsemestre_validate_previous_ue(
moy_ue=moy_ue,
date=date,
semestre_id=semestre_id,
is_external=1,
is_external=True,
)
logdb(

View File

@ -86,6 +86,10 @@ partitionEditor = ndb.EditableTable(
"bul_show_rank",
"show_in_lists",
),
input_formators={
"bul_show_rank": bool,
"show_in_lists": bool,
},
)
groupEditor = ndb.EditableTable(
@ -390,14 +394,15 @@ def formsemestre_get_etud_groupnames(context, formsemestre_id, attr="group_name"
{ etudid : { partition_id : group_name }} (attr=group_name or group_id)
"""
infos = ndb.SimpleDictFetch(
"""SELECT i.id AS etudid, p.is AS partition_id, gd.group_name, gd.id AS group_id
"""SELECT i.id AS etudid, p.id AS partition_id,
gd.group_name, gd.id AS group_id
FROM notes_formsemestre_inscription i, partition p,
group_descr gd, group_membership gm
WHERE i.formsemestre_id=%(formsemestre_id)s
and i.formsemestre_id=p.formsemestre_id
and p.id=gd.partition_id
and gm.etudid=i.etudid
and gm.group_id = gd.group_id
and i.formsemestre_id = p.formsemestre_id
and p.id = gd.partition_id
and gm.etudid = i.etudid
and gm.group_id = gd.id
and p.partition_name is not NULL
""",
{"formsemestre_id": formsemestre_id},
@ -505,9 +510,9 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG
for group in groups:
x_group = Element(
"group",
partition_id=partition_id,
partition_id=str(partition_id),
partition_name=partition["partition_name"],
group_id=group["group_id"],
group_id=str(group["group_id"]),
group_name=group["group_name"],
)
x_response.append(x_group)
@ -516,7 +521,7 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG
x_group.append(
Element(
"etud",
etudid=e["etudid"],
etudid=str(e["etudid"]),
civilite=etud["civilite_str"],
sexe=etud["civilite_str"], # compat
nom=sco_etud.format_nom(etud["nom"]),
@ -531,7 +536,7 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG
if etuds_set:
x_group = Element(
"group",
partition_id=partition_id,
partition_id=str(partition_id),
partition_name=partition["partition_name"],
group_id="_none_",
group_name="",
@ -542,7 +547,7 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG
x_group.append(
Element(
"etud",
etudid=etud["etudid"],
etudid=str(etud["etudid"]),
sexe=etud["civilite_str"],
nom=sco_etud.format_nom(etud["nom"]),
prenom=sco_etud.format_prenom(etud["prenom"]),
@ -618,10 +623,14 @@ def change_etud_group_in_partition(
partition = get_partition(context, group["partition_id"])
# 1- Supprime membership dans cette partition
ndb.SimpleQuery(
"""DELETE FROM group_membership WHERE id IN
"""DELETE FROM group_membership
WHERE id IN
(SELECT gm.id
FROM group_membership gm, group_descr gd
WHERE gm.etudid=%(etudid)s AND gm.group_id=gd.group_id AND gd.partition_id=%(partition_id)s)""",
WHERE gm.etudid = %(etudid)s
AND gm.group_id = gd.id
AND gd.partition_id = %(partition_id)s)
""",
{"etudid": etudid, "partition_id": partition["partition_id"]},
)
@ -688,7 +697,8 @@ def setGroups(
old_members = get_group_members(context, group_id)
old_members_set = set([x["etudid"] for x in old_members])
# Place dans ce groupe les etudiants indiqués:
for etudid in fs[1:-1]:
for etudid_str in fs[1:-1]:
etudid = int(etudid_str)
if etudid in old_members_set:
old_members_set.remove(
etudid
@ -1175,7 +1185,7 @@ def group_set_name(context, group_id, group_name, REQUEST=None, redirect=1):
# redirect to partition edit page:
if redirect:
return flask.redirect("affectGroups?partition_id=" + group["partition_id"])
return flask.redirect("affectGroups?partition_id=" + str(group["partition_id"]))
def group_rename(context, group_id, REQUEST=None):

View File

@ -303,7 +303,7 @@ class DisplayedGroupsInfos(object):
def __init__(
self,
context,
group_ids=[], # groupes specifies dans l'URL
group_ids=[], # groupes specifies dans l'URL, ou un seul int
formsemestre_id=None,
etat=None,
select_all_when_unspecified=False,
@ -311,7 +311,7 @@ class DisplayedGroupsInfos(object):
REQUEST=None,
):
# log('DisplayedGroupsInfos %s' % group_ids)
if isinstance(group_ids, str):
if isinstance(group_ids, int):
if group_ids:
group_ids = [group_ids] # cas ou un seul parametre, pas de liste
else:

View File

@ -436,7 +436,7 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
if etat["evalcomplete"]:
etat_txt = """(prise en compte)"""
etat_descr = "notes utilisées dans les moyennes"
elif eval["publish_incomplete"] != "0":
elif eval["publish_incomplete"]:
etat_txt = """(prise en compte <b>immédiate</b>)"""
etat_descr = (
"il manque des notes, mais la prise en compte immédiate a été demandée"
@ -511,7 +511,7 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
)
)
#
if eval["visibulletin"] == "1":
if eval["visibulletin"]:
H.append(
scu.icontag(
"status_visible_img", title="visible dans bulletins intermédiaires"

View File

@ -146,7 +146,7 @@ class SituationEtudParcoursGeneric(object):
# Verifie barres
self._comp_barres()
# Verifie compensation
if self.prev and self.sem["gestion_compensation"] == "1":
if self.prev and self.sem["gestion_compensation"]:
self.can_compensate_with_prev = self.prev["can_compensate"]
else:
self.can_compensate_with_prev = False
@ -176,10 +176,9 @@ class SituationEtudParcoursGeneric(object):
if rule.conclusion[0] in self.parcours.UNUSED_CODES:
continue
# Saute regles REDOSEM si pas de semestres decales:
if (
self.sem["gestion_semestrielle"] != "1"
and rule.conclusion[3] == "REDOSEM"
):
if (not self.sem["gestion_semestrielle"]) and rule.conclusion[
3
] == "REDOSEM":
continue
if rule.match(state):
if rule.conclusion[0] == ADC:
@ -283,7 +282,7 @@ class SituationEtudParcoursGeneric(object):
(et que le sem courant n soit validé, ce qui n'est pas testé ici)
"""
n = self.sem["semestre_id"]
if self.sem["gestion_semestrielle"] != "1":
if not self.sem["gestion_semestrielle"]:
return False # pas de semestre décalés
if n == NO_SEMESTRE_ID or n > self.parcours.NB_SEM - 2:
return False # n+2 en dehors du parcours
@ -602,7 +601,7 @@ class SituationEtudParcoursGeneric(object):
self.prev["formsemestre_id"],
self.etudid,
decision.new_code_prev,
assidu=1,
assidu=True,
formsemestre_id_utilise_pour_compenser=fsid,
)
logdb(
@ -779,8 +778,14 @@ _scolar_formsemestre_validation_editor = ndb.EditableTable(
"semestre_id",
"is_external",
),
output_formators={"event_date": ndb.DateISOtoDMY, "assidu": bool},
input_formators={"event_date": ndb.DateDMYtoISO, "assidu": bool},
output_formators={
"event_date": ndb.DateISOtoDMY,
},
input_formators={
"event_date": ndb.DateDMYtoISO,
"assidu": bool,
"is_external": bool,
},
)
scolar_formsemestre_validation_create = _scolar_formsemestre_validation_editor.create
@ -837,7 +842,7 @@ def formsemestre_update_validation_sem(
formsemestre_id,
etudid,
code,
assidu=1,
assidu=True,
formsemestre_id_utilise_pour_compenser=None,
):
"Update validation semestre"
@ -845,7 +850,7 @@ def formsemestre_update_validation_sem(
"formsemestre_id": formsemestre_id,
"etudid": etudid,
"code": code,
"assidu": int(assidu),
"assidu": assidu,
}
log("formsemestre_update_validation_sem: %s" % args)
cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)

View File

@ -114,7 +114,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST):
code[etudid] = decision["code"]
if decision["compense_formsemestre_id"]:
code[etudid] += "+" # indique qu'il a servi a compenser
assidu[etudid] = {0: "Non", 1: "Oui"}.get(decision["assidu"], "")
assidu[etudid] = {False: "Non", True: "Oui"}.get(decision["assidu"], "")
aut_list = sco_parcours_dut.formsemestre_get_autorisation_inscription(
context, etudid, formsemestre_id
)

View File

@ -54,6 +54,7 @@ Solution proposée (nov 2014):
"""
import flask
from flask_login import current_user
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
@ -87,9 +88,8 @@ def external_ue_create(
log("external_ue_create( formsemestre_id=%s, titre=%s )" % (formsemestre_id, titre))
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Contrôle d'accès:
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(Permission.ScoImplement):
if not sem["resp_can_edit"] or str(authuser) not in sem["responsables"]:
if not current_user.has_permission(Permission.ScoImplement):
if not sem["resp_can_edit"] or (current_user.id not in sem["responsables"]):
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
#
formation_id = sem["formation_id"]
@ -107,7 +107,7 @@ def external_ue_create(
"numero": numero,
"type": ue_type,
"ects": ects,
"is_external": 1,
"is_external": True,
},
)
@ -170,9 +170,9 @@ def external_ue_inscrit_et_note(
moduleimpl_id=moduleimpl_id,
note_max=20.0,
coefficient=1.0,
publish_incomplete=1,
evaluation_type=0,
visibulletin=0,
publish_incomplete=True,
evaluation_type=scu.EVALUATION_NORMALE,
visibulletin=False,
description="note externe",
)
# Saisie des notes
@ -188,7 +188,7 @@ def external_ue_inscrit_et_note(
def get_existing_external_ue(context, formation_id):
"la liste de toutes les UE externes définies dans cette formation"
return sco_edit_ue.do_ue_list(
context, args={"formation_id": formation_id, "is_external": 1}
context, args={"formation_id": formation_id, "is_external": True}
)
@ -221,9 +221,8 @@ def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None):
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Contrôle d'accès:
authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(Permission.ScoImplement):
if not sem["resp_can_edit"] or str(authuser) not in sem["responsables"]:
if not current_user.has_permission(Permission.ScoImplement):
if not sem["resp_can_edit"] or (current_user.id not in sem["responsables"]):
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
etud = sco_etud.get_etud_info(etudid=etudid, filled=1, REQUEST=REQUEST)[0]

View File

@ -449,9 +449,13 @@ def stripquotes(s):
def suppress_accents(s):
"remove accents and suppress non ascii characters from string s"
if isinstance(s, str):
return (
unicodedata.normalize("NFD", s).encode("ascii", "ignore").decode(SCO_ENCODING)
unicodedata.normalize("NFD", s)
.encode("ascii", "ignore")
.decode(SCO_ENCODING)
)
return s # may be int
def sanitize_string(s):

View File

@ -1189,7 +1189,7 @@ def _tableBillets(context, billets, etud=None, title=""):
m = " après-midi"
b["abs_end_str"] = b["abs_end"].strftime("%d/%m/%Y") + m
if b["etat"] == 0:
if b["justified"] == 0:
if b["justified"]:
b["etat_str"] = "à traiter"
else:
b["etat_str"] = "à justifier"
@ -1441,7 +1441,7 @@ def ProcessBilletAbsenceForm(context, billet_id, REQUEST=None):
if tf[0] == 0:
tab = _tableBillets(context, [billet], etud=etud)
H.append(tab.html())
if billet["justified"] == 1:
if billet["justified"]:
H.append(
"""<p>L'étudiant pense pouvoir justifier cette absence.<br/><em>Vérifiez le justificatif avant d'enregistrer.</em></p>"""
)

View File

@ -640,6 +640,7 @@ sco_publish(
"/formsemestre_change_publication_bul",
sco_formsemestre_edit.formsemestre_change_publication_bul,
Permission.ScoView,
methods=["GET", "POST"],
)
sco_publish(
"/view_formsemestre_by_etape",
@ -746,7 +747,7 @@ def edit_enseignants_form(context, REQUEST, moduleimpl_id):
elif tf[0] == -1:
return flask.redirect("moduleimpl_status?moduleimpl_id=" + moduleimpl_id)
else:
ens_id = User.get_user_name_from_nomplogin(tf[2]["ens_id"])
ens_id = User.get_user_id_from_nomplogin(tf[2]["ens_id"])
if not ens_id:
H.append(
'<p class="help">Pour ajouter un enseignant, choisissez un nom dans le menu</p>'
@ -838,7 +839,7 @@ def edit_moduleimpl_resp(context, REQUEST, moduleimpl_id):
elif tf[0] == -1:
return flask.redirect("moduleimpl_status?moduleimpl_id=" + moduleimpl_id)
else:
responsable_id = User.get_user_name_from_nomplogin(tf[2]["responsable_id"])
responsable_id = User.get_user_id_from_nomplogin(tf[2]["responsable_id"])
if (
not responsable_id
): # presque impossible: tf verifie les valeurs (mais qui peuvent changer entre temps)

View File

@ -703,6 +703,18 @@ sco_publish(
Permission.ScoView,
methods=["GET", "POST"],
)
# @bp.route("/partition_create", methods=["GET", "POST"])
# @permission_required(Permission.ScoView)
# @scodoc7func(context)
# def partition_create(
# context,
# formsemestre_id,
# partition_name="",
# default=False,
# numero=None,
# redirect=1):
# return sco_groups.partition_create(context, formsemestre_id,
sco_publish("/etud_info_html", sco_page_etud.etud_info_html, Permission.ScoView)

View File

@ -43,22 +43,29 @@ mi = G.create_moduleimpl(
# --- Création d'un étudiant
etud = G.create_etud(code_nip=None)
G.inscrit_etudiant(sem, etud)
etudid=etud["etudid"]
etudid = etud["etudid"]
# --- Création d'une absence
sco_abs_views.doSignaleAbsence(context.Absences, datedebut="22/01/2021", datefin="22/01/2021", demijournee=2, etudid=etudid, REQUEST=REQUEST)
sco_abs_views.doSignaleAbsence(
context.Absences,
datedebut="22/01/2021",
datefin="22/01/2021",
demijournee=2,
etudid=etudid,
REQUEST=REQUEST,
)
# --- Création d'un billet
b1 = context.Absences.AddBilletAbsence(
begin="2021-01-22 00:00",
end="2021-01-22 23:59",
etudid=etudid,
description = "abs du 22",
description="abs du 22",
justified=False,
code_nip=etuds[0]["code_nip"],
code_ine=etuds[0]["code_ine"],
REQUEST=REQUEST,
)
)
# --- Suppression d'un billet
_ = context.Absences.deleteBilletAbsence(load_li_bi[1]["billet_id"], REQUEST=REQUEST)

View File

@ -132,7 +132,7 @@ def run_sco_basic(verbose=False):
assert etat["evalcomplete"]
# Modifie l'évaluation 2 pour "prise en compte immédiate"
e2["publish_incomplete"] = "1"
e2["publish_incomplete"] = True
sco_evaluations.do_evaluation_edit(e2)
etat = sco_evaluations.do_evaluation_etat(e2["evaluation_id"])
assert etat["evalcomplete"] == False