Modifie conditions de vérrouillage UE: adaptation à l'APC

This commit is contained in:
Emmanuel Viennet 2024-09-16 17:01:47 +02:00
parent 19373c10c0
commit 75e5948dfe
6 changed files with 61 additions and 30 deletions

View File

@ -184,11 +184,8 @@ class UniteEns(models.ScoDocModel):
"""
return 1 if self.semestre_idx is None else (self.semestre_idx - 1) // 2 + 1
def is_locked(self):
"""True if UE should not be modified
(contains modules used in a locked formsemestre)
"""
# XXX todo : à ré-écrire avec SQLAlchemy
def is_locked(self) -> tuple[bool, str]:
"""True if UE should not be modified"""
from app.scodoc import sco_edit_ue
return sco_edit_ue.ue_is_locked(self.id)

View File

@ -215,9 +215,11 @@ def html_ue_infos(ue):
and ue.modules.count() == 0
and ue.matieres.count() == 0
)
titre = f"UE {ue.acronyme} {ue.titre or ''}"
return render_template(
"pn/ue_infos.j2",
titre=f"UE {ue.acronyme} {ue.titre or ''}",
title=titre, # titre html de la page
titre=titre, # dans la page
ue=ue,
formsemestres=formsemestres,
nb_etuds_valid_ue=nb_etuds_valid_ue,

View File

@ -44,6 +44,8 @@ from app.models import (
FormSemestreUEComputationExpr,
FormSemestreUECoef,
Matiere,
Module,
ModuleImpl,
UniteEns,
)
from app.models import ApcValidationRCUE, ScolarFormSemestreValidation, ScolarEvent
@ -59,7 +61,6 @@ from app.scodoc.sco_exceptions import (
ScoNonEmptyFormationObject,
)
from app.scodoc import html_sco_header
from app.scodoc import codes_cursus
from app.scodoc import sco_edit_apc
from app.scodoc import sco_edit_matiere
@ -1066,10 +1067,12 @@ du programme" (menu "Semestre") si vous avez un semestre en cours);
warn, _ = sco_formsemestre_validation.check_formation_ues(formation)
H.append(warn)
titre = f"Programme {formation.acronyme} v{formation.version}"
return render_template(
"sco_page_dept.j2",
content="".join(H),
page_title=f"Formation {formation.acronyme} v{formation.version}",
title=titre,
page_title=titre,
cssstyles=["libjs/jQuery-tagEditor/jquery.tag-editor.css", "css/ue_table.css"],
javascripts=[
"libjs/jinplace-1.2.1.min.js",
@ -1200,7 +1203,8 @@ def _ue_table_ues(
}">transformer en UE ordinaire</a>&nbsp;"""
)
H.append("</span>")
ue_editable = editable and not ue_is_locked(ue["ue_id"])
ue_locked, ue_locked_reason = ue_is_locked(ue["ue_id"])
ue_editable = editable and not ue_locked
if ue_editable:
H.append(
f"""<a class="stdlink" href="{
@ -1208,7 +1212,9 @@ def _ue_table_ues(
}">modifier</a>"""
)
else:
H.append('<span class="locked">[verrouillé]</span>')
H.append(
f'<span class="locked fontred">[verrouillée: {ue_locked_reason}]</span>'
)
H.append(
_ue_table_matieres(
parcours,
@ -1500,8 +1506,10 @@ def do_ue_edit(args, bypass_lock=False, dont_invalidate_cache=False):
# check
ue_id = args["ue_id"]
ue = ue_list({"ue_id": ue_id})[0]
if (not bypass_lock) and ue_is_locked(ue["ue_id"]):
raise ScoLockedFormError()
if not bypass_lock:
ue_locked, ue_locked_reason = ue_is_locked(ue["ue_id"])
if ue_locked:
raise ScoLockedFormError(msg=f"UE verrouillée: {ue_locked_reason}")
# check: acronyme unique dans cette formation
if "acronyme" in args:
new_acro = args["acronyme"]
@ -1525,20 +1533,38 @@ def do_ue_edit(args, bypass_lock=False, dont_invalidate_cache=False):
formation.invalidate_module_coefs()
def ue_is_locked(ue_id):
"""True if UE should not be modified
(contains modules used in a locked formsemestre)
def ue_is_locked(ue_id: int) -> tuple[bool, str]:
"""True if UE should not be modified:
utilisée dans un formsemestre verrouillé ou validations de jury de cette UE.
Renvoie aussi une explication.
"""
r = ndb.SimpleDictFetch(
"""SELECT ue.id
FROM notes_ue ue, notes_modules mod, notes_formsemestre sem, notes_moduleimpl mi
WHERE ue.id = mod.ue_id
AND mi.module_id = mod.id AND mi.formsemestre_id = sem.id
AND ue.id = %(ue_id)s AND sem.etat = false
""",
{"ue_id": ue_id},
)
return len(r) > 0
# before 9.7.23: contains modules used in a locked formsemestre
# starting from 9.7.23: + existence de validations de jury de cette UE
ue = UniteEns.query.get(ue_id)
if not ue:
return True, "inexistante"
if ue.formation.is_apc():
# en APC, interdit toute modification d'UE si utilisée dans un semestre verrouillé
if False in [formsemestre.etat for formsemestre in ue.formation.formsemestres]:
return True, "utilisée dans un semestre verrouillé"
else:
# en classique: interdit si contient des modules utilisés dans des semestres verrouillés
# en effet, dans certaines (très anciennes) formations, une UE peut avoir des modules de
# différents semestre
if (
Module.query.filter(Module.ue_id == ue_id)
.join(Module.modimpls)
.join(ModuleImpl.formsemestre)
.filter_by(etat=False)
.count()
):
return True, "avec modules utilisés dans des semestres verrouillés"
nb_validations = ScolarFormSemestreValidation.query.filter_by(ue_id=ue_id).count()
if nb_validations > 0:
return True, f"avec {nb_validations} validations de jury"
return False, ""
UE_PALETTE = [

View File

@ -1185,6 +1185,9 @@ span.trombi_box a img {
}
/* markup non semantique pour les cas simples */
.smallnote {
font-size: 80%;
}
.fontred {
color: red;

View File

@ -81,10 +81,13 @@
{% endfor %}
</div>
{% endif %}
{% if editable and not ue.is_locked() %}
{% set ue_is_locked = ue.is_locked() %}
{% if editable and not ue_is_locked[0] %}
<a class="stdlink" href="{{ url_for('notes.ue_edit',
scodoc_dept=g.scodoc_dept, ue_id=ue.id)
}}">modifier</a>
{% else %}
<span class ="fontred smallnote">{{ue_is_locked[1]}}</span>
{% endif %}
{% if ue.type != codes_cursus.UE_SPORT %}
@ -98,7 +101,7 @@
pas de niveau de compétence associé !
</span>
{% endif %}
{% if editable and not ue.is_locked() %}
{% if editable and not ue_is_locked[0] %}
<a class="stdlink" href="{{
url_for('notes.parcour_formation', scodoc_dept=g.scodoc_dept,
formation_id=formation.id )

View File

@ -58,8 +58,8 @@
</ul>
<ul>
{% if ue.is_locked %}
<li><em>non modifiable car utilisée dans des semestres verrouillés</em></li>
{% if ue.is_locked()[0] %}
<li><em class="fontred">non modifiable : {{ue.is_locked()[1]}}</em></li>
{% else %}
<li><a href="{{url_for('notes.ue_edit', scodoc_dept=g.scodoc_dept, ue_id=ue.id)}}">modifier cette UE</a>
</li>