diff --git a/app/models/formations.py b/app/models/formations.py
index fd1f01895..3d63b1b75 100644
--- a/app/models/formations.py
+++ b/app/models/formations.py
@@ -143,11 +143,15 @@ class Module(db.Model):
def set_ue_coef_dict(self, ue_coef_dict: dict) -> None:
"""set coefs vers les UE (remplace existants)
ue_coef_dict = { ue_id : coef }
+ Les coefs nuls (zéro) ne sont pas stockés: la relation est supprimée.
"""
ue_coefs = []
for ue_id, coef in ue_coef_dict.items():
ue = UniteEns.query.get(ue_id)
- ue_coefs.append(ModuleUECoef(module=self, ue=ue, coef=coef))
+ if coef == 0.0:
+ self.delete_ue_coef(ue)
+ else:
+ ue_coefs.append(ModuleUECoef(module=self, ue=ue, coef=coef))
self.ue_coefs = ue_coefs
def update_ue_coef_dict(self, ue_coef_dict: dict):
@@ -163,7 +167,12 @@ class Module(db.Model):
def delete_ue_coef(self, ue):
"""delete coef"""
ue_coef = ModuleUECoef.query.get((self.id, ue.id))
- db.session.delete(ue_coef)
+ if ue_coef:
+ db.session.delete(ue_coef)
+
+ def ue_coefs_descr(self):
+ """List of tuples [ (ue_acronyme, coef) ]"""
+ return [(c.ue.acronyme, c.coef) for c in self.ue_coefs]
class ModuleUECoef(db.Model):
diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py
index 9fcb75a48..979ed3af7 100644
--- a/app/scodoc/sco_edit_module.py
+++ b/app/scodoc/sco_edit_module.py
@@ -37,6 +37,7 @@ import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import ModuleType
from app import log
+from app import models
from app.scodoc.TrivialFormulator import TrivialFormulator
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError, ScoGenError
@@ -344,9 +345,8 @@ def module_edit(module_id=None):
raise ScoValueError("invalid module !")
module = modules[0]
unlocked = not module_is_locked(module_id)
- formation = sco_formations.formation_list(
- args={"formation_id": module["formation_id"]}
- )[0]
+ formation_id = module["formation_id"]
+ formation = sco_formations.formation_list(args={"formation_id": formation_id})[0]
parcours = sco_codes_parcours.get_parcours_from_code(formation["type_parcours"])
is_apc = parcours.APC_SAE
ues_matieres = ndb.SimpleDictFetch(
@@ -356,7 +356,7 @@ def module_edit(module_id=None):
AND ue.formation_id = %(formation_id)s
ORDER BY ue.numero, mat.numero
""",
- {"formation_id": module["formation_id"]},
+ {"formation_id": formation_id},
)
mat_names = ["%s / %s" % (x["acronyme"], x["titre"]) for x in ues_matieres]
ue_mat_ids = ["%s!%s" % (x["ue_id"], x["matiere_id"]) for x in ues_matieres]
@@ -366,7 +366,7 @@ def module_edit(module_id=None):
dest_url = url_for(
"notes.ue_table",
scodoc_dept=g.scodoc_dept,
- formation_id=str(module["formation_id"]),
+ formation_id=str(formation_id),
)
H = [
html_sco_header.sco_header(
@@ -387,56 +387,72 @@ def module_edit(module_id=None):
"""
Formation verrouillée, seuls certains éléments peuvent être modifiés
"""
)
- tf = TrivialFormulator(
- request.base_url,
- scu.get_request_args(),
+ descr = [
(
+ "code",
+ {
+ "size": 10,
+ "explanation": "code du module (doit être unique dans la formation)",
+ "allow_null": False,
+ "validator": lambda val, field, formation_id=formation_id: check_module_code_unicity(
+ val, field, formation_id, module_id=module_id
+ ),
+ },
+ ),
+ ("titre", {"size": 30, "explanation": "nom du module"}),
+ ("abbrev", {"size": 20, "explanation": "nom abrégé (pour bulletins)"}),
+ (
+ "module_type",
+ {
+ "input_type": "menu",
+ "title": "Type",
+ "explanation": "",
+ "labels": [x.name.capitalize() for x in scu.ModuleType],
+ "allowed_values": [str(int(x)) for x in scu.ModuleType],
+ "enabled": unlocked,
+ },
+ ),
+ (
+ "heures_cours",
+ {"size": 4, "type": "float", "explanation": "nombre d'heures de cours"},
+ ),
+ (
+ "heures_td",
+ {
+ "size": 4,
+ "type": "float",
+ "explanation": "nombre d'heures de Travaux Dirigés",
+ },
+ ),
+ (
+ "heures_tp",
+ {
+ "size": 4,
+ "type": "float",
+ "explanation": "nombre d'heures de Travaux Pratiques",
+ },
+ ),
+ ]
+ if is_apc:
+ a_module = models.Module.query.get(module_id)
+ coefs_descr = a_module.ue_coefs_descr()
+ if coefs_descr:
+ coefs_descr_txt = ", ".join(["%s: %s" % x for x in coefs_descr])
+ else:
+ coefs_descr_txt = """non définis"""
+ descr += [
(
- "code",
+ "ue_coefs",
{
- "size": 10,
- "explanation": "code du module (doit être unique dans la formation)",
- "allow_null": False,
- "validator": lambda val, field, formation_id=module[
- "formation_id"
- ]: check_module_code_unicity(
- val, field, formation_id, module_id=module_id
- ),
+ "readonly": True,
+ "title": "Coefficients vers les UE",
+ "default": coefs_descr_txt,
+ "explanation": "passer par la page d'édition de la formation pour modifier les coefficients",
},
- ),
- ("titre", {"size": 30, "explanation": "nom du module"}),
- ("abbrev", {"size": 20, "explanation": "nom abrégé (pour bulletins)"}),
- (
- "module_type",
- {
- "input_type": "menu",
- "title": "Type",
- "explanation": "",
- "labels": [x.name.capitalize() for x in scu.ModuleType],
- "allowed_values": [str(int(x)) for x in scu.ModuleType],
- "enabled": unlocked,
- },
- ),
- (
- "heures_cours",
- {"size": 4, "type": "float", "explanation": "nombre d'heures de cours"},
- ),
- (
- "heures_td",
- {
- "size": 4,
- "type": "float",
- "explanation": "nombre d'heures de Travaux Dirigés",
- },
- ),
- (
- "heures_tp",
- {
- "size": 4,
- "type": "float",
- "explanation": "nombre d'heures de Travaux Pratiques",
- },
- ),
+ )
+ ]
+ else: # Module classique avec coef scalaire:
+ descr += [
(
"coefficient",
{
@@ -447,51 +463,57 @@ def module_edit(module_id=None):
"enabled": unlocked,
},
),
- # ('ects', { 'size' : 4, 'type' : 'float', 'title' : 'ECTS', 'explanation' : 'nombre de crédits ECTS', 'enabled' : unlocked }),
- ("formation_id", {"input_type": "hidden"}),
- ("ue_id", {"input_type": "hidden"}),
- ("module_id", {"input_type": "hidden"}),
- (
- "ue_matiere_id",
- {
- "input_type": "menu",
- "title": "Matière",
- "explanation": "un module appartient à une seule matière.",
- "labels": mat_names,
- "allowed_values": ue_mat_ids,
- "enabled": unlocked,
- },
- ),
- (
- "semestre_id",
- {
- "input_type": "menu",
- "type": "int",
- "title": parcours.SESSION_NAME.capitalize(),
- "explanation": "%s de début du module dans la formation standard"
- % parcours.SESSION_NAME,
- "labels": [str(x) for x in semestres_indices],
- "allowed_values": semestres_indices,
- "enabled": unlocked,
- },
- ),
- (
- "code_apogee",
- {
- "title": "Code Apogée",
- "size": 25,
- "explanation": "(optionnel) code élément pédagogique Apogée ou liste de codes ELP séparés par des virgules",
- },
- ),
- (
- "numero",
- {
- "size": 2,
- "explanation": "numéro (1,2,3,4...) pour ordre d'affichage",
- "type": "int",
- },
- ),
+ ]
+ descr += [
+ ("formation_id", {"input_type": "hidden"}),
+ ("ue_id", {"input_type": "hidden"}),
+ ("module_id", {"input_type": "hidden"}),
+ (
+ "ue_matiere_id",
+ {
+ "input_type": "menu",
+ "title": "Matière",
+ "explanation": "un module appartient à une seule matière.",
+ "labels": mat_names,
+ "allowed_values": ue_mat_ids,
+ "enabled": unlocked,
+ },
),
+ (
+ "semestre_id",
+ {
+ "input_type": "menu",
+ "type": "int",
+ "title": parcours.SESSION_NAME.capitalize(),
+ "explanation": "%s de début du module dans la formation standard"
+ % parcours.SESSION_NAME,
+ "labels": [str(x) for x in semestres_indices],
+ "allowed_values": semestres_indices,
+ "enabled": unlocked,
+ },
+ ),
+ (
+ "code_apogee",
+ {
+ "title": "Code Apogée",
+ "size": 25,
+ "explanation": "(optionnel) code élément pédagogique Apogée ou liste de codes ELP séparés par des virgules",
+ },
+ ),
+ (
+ "numero",
+ {
+ "size": 2,
+ "explanation": "numéro (1,2,3,4...) pour ordre d'affichage",
+ "type": "int",
+ },
+ ),
+ ]
+
+ tf = TrivialFormulator(
+ request.base_url,
+ scu.get_request_args(),
+ descr,
html_foot_markup="""
""".format(
module_id, ",".join(sco_tag_module.module_tag_list(module_id))
),
diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py
index 232e3cb87..0591fd080 100644
--- a/app/scodoc/sco_edit_ue.py
+++ b/app/scodoc/sco_edit_ue.py
@@ -453,6 +453,7 @@ def ue_table(formation_id=None, msg=""): # was ue_list
raise ScoValueError("invalid formation_id")
F = F[0]
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"])
+ is_apc = parcours.APC_SAE
locked = sco_formations.formation_has_locked_sems(formation_id)
ues = ue_list(args={"formation_id": formation_id, "is_external": False})
@@ -568,7 +569,18 @@ du programme" (menu "Semestre") si vous avez un semestre en cours);
)
H.append("")
-
+ # Formation APC (BUT) ?
+ if is_apc:
+ H.append(
+ f""""""
+ )
# Description des UE/matières/modules
H.append('