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 return 1 if self.semestre_idx is None else (self.semestre_idx - 1) // 2 + 1
def is_locked(self): def is_locked(self) -> tuple[bool, str]:
"""True if UE should not be modified """True if UE should not be modified"""
(contains modules used in a locked formsemestre)
"""
# XXX todo : à ré-écrire avec SQLAlchemy
from app.scodoc import sco_edit_ue from app.scodoc import sco_edit_ue
return sco_edit_ue.ue_is_locked(self.id) 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.modules.count() == 0
and ue.matieres.count() == 0 and ue.matieres.count() == 0
) )
titre = f"UE {ue.acronyme} {ue.titre or ''}"
return render_template( return render_template(
"pn/ue_infos.j2", "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, ue=ue,
formsemestres=formsemestres, formsemestres=formsemestres,
nb_etuds_valid_ue=nb_etuds_valid_ue, nb_etuds_valid_ue=nb_etuds_valid_ue,

View File

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

View File

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

View File

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

View File

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