Update opolka/ScoDoc from ScoDoc/ScoDoc #2

Merged
opolka merged 1272 commits from ScoDoc/ScoDoc:master into master 2024-05-27 09:11:04 +02:00
7 changed files with 133 additions and 32 deletions
Showing only changes of commit c0a965d774 - Show all commits

View File

@ -77,7 +77,7 @@ from app.models.but_refcomp import (
ApcNiveau, ApcNiveau,
ApcParcours, ApcParcours,
) )
from app.models import Scolog, ScolarAutorisationInscription from app.models import Evaluation, Scolog, ScolarAutorisationInscription
from app.models.but_validations import ( from app.models.but_validations import (
ApcValidationAnnee, ApcValidationAnnee,
ApcValidationRCUE, ApcValidationRCUE,
@ -260,11 +260,11 @@ class DecisionsProposeesAnnee(DecisionsProposees):
else [] else []
) )
# ---- Niveaux et RCUEs # ---- Niveaux et RCUEs
niveaux_by_parcours = ( niveaux_by_parcours = formsemestre.formation.referentiel_competence.get_niveaux_by_parcours(
formsemestre.formation.referentiel_competence.get_niveaux_by_parcours(
self.annee_but, [self.parcour] if self.parcour else None self.annee_but, [self.parcour] if self.parcour else None
)[1] )[
) 1
]
self.niveaux_competences = niveaux_by_parcours["TC"] + ( self.niveaux_competences = niveaux_by_parcours["TC"] + (
niveaux_by_parcours[self.parcour.id] if self.parcour else [] niveaux_by_parcours[self.parcour.id] if self.parcour else []
) )
@ -358,13 +358,17 @@ class DecisionsProposeesAnnee(DecisionsProposees):
# self.codes = [] # pas de décision annuelle sur semestres impairs # self.codes = [] # pas de décision annuelle sur semestres impairs
elif self.inscription_etat != scu.INSCRIT: elif self.inscription_etat != scu.INSCRIT:
self.codes = [ self.codes = [
(
sco_codes.DEM sco_codes.DEM
if self.inscription_etat == scu.DEMISSION if self.inscription_etat == scu.DEMISSION
else sco_codes.DEF, else sco_codes.DEF
),
# propose aussi d'autres codes, au cas où... # propose aussi d'autres codes, au cas où...
(
sco_codes.DEM sco_codes.DEM
if self.inscription_etat != scu.DEMISSION if self.inscription_etat != scu.DEMISSION
else sco_codes.DEF, else sco_codes.DEF
),
sco_codes.ABAN, sco_codes.ABAN,
sco_codes.ABL, sco_codes.ABL,
sco_codes.EXCLU, sco_codes.EXCLU,
@ -595,11 +599,9 @@ class DecisionsProposeesAnnee(DecisionsProposees):
# Ordonne par numéro d'UE # Ordonne par numéro d'UE
niv_rcue = sorted( niv_rcue = sorted(
self.rcue_by_niveau.items(), self.rcue_by_niveau.items(),
key=lambda x: x[1].ue_1.numero key=lambda x: (
if x[1].ue_1 x[1].ue_1.numero if x[1].ue_1 else x[1].ue_2.numero if x[1].ue_2 else 0
else x[1].ue_2.numero ),
if x[1].ue_2
else 0,
) )
return { return {
niveau_id: DecisionsProposeesRCUE(self, rcue, self.inscription_etat) niveau_id: DecisionsProposeesRCUE(self, rcue, self.inscription_etat)
@ -816,8 +818,14 @@ class DecisionsProposeesAnnee(DecisionsProposees):
Return: True si au moins un code modifié et enregistré. Return: True si au moins un code modifié et enregistré.
""" """
modif = False modif = False
# Vérification notes en attente dans formsemestre origine if only_validantes:
if only_validantes and self.has_notes_en_attente(): if self.has_notes_en_attente():
# notes en attente dans formsemestre origine
return False
if Evaluation.get_evaluations_blocked_for_etud(
self.formsemestre, self.etud
):
# évaluation(s) qui seront débloquées dans le futur
return False return False
# Toujours valider dans l'ordre UE, RCUE, Année # Toujours valider dans l'ordre UE, RCUE, Année
@ -1488,9 +1496,11 @@ class DecisionsProposeesUE(DecisionsProposees):
self.validation = None # cache toute validation self.validation = None # cache toute validation
self.explanation = "non inscrit (dem. ou déf.)" self.explanation = "non inscrit (dem. ou déf.)"
self.codes = [ self.codes = [
(
sco_codes.DEM sco_codes.DEM
if res.get_etud_etat(etud.id) == scu.DEMISSION if res.get_etud_etat(etud.id) == scu.DEMISSION
else sco_codes.DEF else sco_codes.DEF
)
] ]
return return

View File

@ -488,6 +488,29 @@ class Evaluation(models.ScoDocModel):
""" """
return NotesNotes.query.filter_by(etudid=etud.id, evaluation_id=self.id).first() return NotesNotes.query.filter_by(etudid=etud.id, evaluation_id=self.id).first()
@classmethod
def get_evaluations_blocked_for_etud(
cls, formsemestre, etud: Identite
) -> list["Evaluation"]:
"""Liste des évaluations de ce semestre avec note pour cet étudiant et date blocage
et date blocage < FOREVER.
Si non vide, une note apparaitra dans le futur pour cet étudiant: il faut
donc interdire la saisie du jury.
"""
now = datetime.datetime.now(scu.TIME_ZONE)
return (
Evaluation.query.filter(
Evaluation.blocked_until != None, # pylint: disable=C0121
Evaluation.blocked_until >= now,
)
.join(ModuleImpl)
.filter_by(formsemestre_id=formsemestre.id)
.join(ModuleImplInscription)
.filter_by(etudid=etud.id)
.join(NotesNotes)
.all()
)
class EvaluationUEPoids(db.Model): class EvaluationUEPoids(db.Model):
"""Poids des évaluations (BUT) """Poids des évaluations (BUT)
@ -657,3 +680,6 @@ def _moduleimpl_evaluation_insert_before(
db.session.add(e) db.session.add(e)
db.session.commit() db.session.commit()
return n return n
from app.models.moduleimpls import ModuleImpl, ModuleImplInscription

View File

@ -34,7 +34,7 @@ from flask import url_for, flash, g, request
from flask_login import current_user from flask_login import current_user
import sqlalchemy as sa import sqlalchemy as sa
from app.models.etudiants import Identite from app.models import Identite, Evaluation
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import db, log from app import db, log
@ -232,7 +232,9 @@ def formsemestre_validation_etud_form(
H.append( H.append(
tf_error_message( tf_error_message(
f"""Impossible de statuer sur cet étudiant: il a des notes en f"""Impossible de statuer sur cet étudiant: il a des notes en
attente dans des évaluations de ce semestre (voir <a href="{ attente dans des évaluations de ce semestre (voir
<a class="stdlink"
href="{
url_for( "notes.formsemestre_status", url_for( "notes.formsemestre_status",
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id) scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
}">tableau de bord</a>) }">tableau de bord</a>)
@ -241,6 +243,26 @@ def formsemestre_validation_etud_form(
) )
return "\n".join(H + footer) return "\n".join(H + footer)
evaluations_a_debloquer = Evaluation.get_evaluations_blocked_for_etud(
formsemestre, etud
)
if evaluations_a_debloquer:
links_evals = [
f"""<a class="stdlink" href="{url_for(
'notes.evaluation_listenotes', scodoc_dept=g.scodoc_dept, evaluation_id=e.id
)}">{e.description} en {e.moduleimpl.module.code}</a>"""
for e in evaluations_a_debloquer
]
H.append(
tf_error_message(
f"""Impossible de statuer sur cet étudiant:
il a des notes dans des évaluations qui seront débloquées plus tard:
voir {", ".join(links_evals)}
"""
)
)
return "\n".join(H + footer)
# Infos si pas de semestre précédent # Infos si pas de semestre précédent
if not Se.prev: if not Se.prev:
if Se.sem["semestre_id"] == 1: if Se.sem["semestre_id"] == 1:

View File

@ -3391,14 +3391,24 @@ li.tf-msg {
padding-bottom: 5px; padding-bottom: 5px;
} }
.warning { .warning, .warning-bloquant {
font-weight: bold;
color: red; color: red;
margin-left: 16px;
margin-bottom: 8px;
min-width: var(--sco-content-min-width);
max-width: var(--sco-content-max-width);
} }
.warning::before { .warning::before {
content: url(/ScoDoc/static/icons/warning_img.png); content:"";
vertical-align: -80%; margin-right: 8px;
height:32px;
width: 32px;
background-size: 32px 32px;
background-image: url(/ScoDoc/static/icons/warning_std.svg);
background-repeat: no-repeat;
display: inline-block;
vertical-align: -40%;
} }
.warning-light { .warning-light {
@ -3411,6 +3421,19 @@ li.tf-msg {
/* EMO_WARNING, "&#9888;&#65039;" */ /* EMO_WARNING, "&#9888;&#65039;" */
} }
.warning-bloquant::before {
content:"";
margin-right: 8px;
height:32px;
width: 32px;
background-size: 32px 32px;
background-image: url(/ScoDoc/static/icons/warning_bloquant.svg);
background-repeat: no-repeat;
display: inline-block;
vertical-align: -40%;
}
p.error { p.error {
font-weight: bold; font-weight: bold;
color: red; color: red;

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -0,0 +1 @@
<svg id="Capa_1" enable-background="new 0 0 512 512" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m208.587 54.407-201.17 348.437c-21.073 36.499 5.268 82.122 47.413 82.122h402.34c42.145 0 68.486-45.624 47.413-82.122l-201.17-348.437c-21.072-36.498-73.754-36.498-94.826 0z" fill="#da4a54"/><path d="m54.83 443.76c-6.802 0-10.267-4.242-11.727-6.771s-3.401-7.65 0-13.542l201.17-348.436c3.401-5.891 8.807-6.771 11.727-6.771s8.326.88 11.727 6.771l201.17 348.436c3.401 5.891 1.46 11.013 0 13.541-1.46 2.529-4.925 6.771-11.727 6.771h-402.34z" fill="#f6e266"/><g fill="#544f57"><path d="m256 327.138c-14.379 0-26.036-11.657-26.036-26.036v-119.216c0-14.379 11.657-26.036 26.036-26.036 14.379 0 26.036 11.657 26.036 26.036v119.217c0 14.379-11.657 26.035-26.036 26.035z"/><circle cx="256" cy="381.152" r="26.036"/></g></svg>

After

Width:  |  Height:  |  Size: 857 B

View File

@ -2408,6 +2408,12 @@ def formsemestre_validation_but(
) )
deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre) deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
has_notes_en_attente = deca.has_notes_en_attente()
evaluations_a_debloquer = Evaluation.get_evaluations_blocked_for_etud(
formsemestre, etud
)
if has_notes_en_attente or evaluations_a_debloquer:
read_only = True
if request.method == "POST": if request.method == "POST":
if not read_only: if not read_only:
deca.record_form(request.form) deca.record_form(request.form)
@ -2452,9 +2458,21 @@ def formsemestre_validation_but(
etat_ins = scu.ETATS_INSCRIPTION.get(inscription.etat, "inconnu?") etat_ins = scu.ETATS_INSCRIPTION.get(inscription.etat, "inconnu?")
warning += f"""<div class="warning">{etat_ins} en S{deca.formsemestre_pair.semestre_id}</div>""" warning += f"""<div class="warning">{etat_ins} en S{deca.formsemestre_pair.semestre_id}</div>"""
if deca.has_notes_en_attente(): if has_notes_en_attente:
warning += f"""<div class="warning">{etud.nomprenom} a des notes en ATTente. warning += f"""<div class="warning-bloquant">{etud.nomprenom} a des notes en ATTente.
Vous devriez régler cela avant de statuer en jury !</div>""" Vous devez régler cela avant de statuer en jury !</div>"""
if evaluations_a_debloquer:
links_evals = [
f"""<a class="stdlink" href="{url_for(
'notes.evaluation_listenotes', scodoc_dept=g.scodoc_dept, evaluation_id=e.id
)}">{e.description} en {e.moduleimpl.module.code}</a>"""
for e in evaluations_a_debloquer
]
warning += f"""<div class="warning-bloquant">Impossible de statuer sur cet étudiant:
il a des notes dans des évaluations qui seront débloquées plus tard:
voir {", ".join(links_evals)}
"""
H.append( H.append(
f""" f"""
<div> <div>