forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
@ -77,7 +77,7 @@ from app.models.but_refcomp import (
|
||||
ApcNiveau,
|
||||
ApcParcours,
|
||||
)
|
||||
from app.models import Scolog, ScolarAutorisationInscription
|
||||
from app.models import Evaluation, Scolog, ScolarAutorisationInscription
|
||||
from app.models.but_validations import (
|
||||
ApcValidationAnnee,
|
||||
ApcValidationRCUE,
|
||||
@ -260,11 +260,11 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
else []
|
||||
)
|
||||
# ---- Niveaux et RCUEs
|
||||
niveaux_by_parcours = (
|
||||
formsemestre.formation.referentiel_competence.get_niveaux_by_parcours(
|
||||
self.annee_but, [self.parcour] if self.parcour else None
|
||||
)[1]
|
||||
)
|
||||
niveaux_by_parcours = formsemestre.formation.referentiel_competence.get_niveaux_by_parcours(
|
||||
self.annee_but, [self.parcour] if self.parcour else None
|
||||
)[
|
||||
1
|
||||
]
|
||||
self.niveaux_competences = niveaux_by_parcours["TC"] + (
|
||||
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
|
||||
elif self.inscription_etat != scu.INSCRIT:
|
||||
self.codes = [
|
||||
sco_codes.DEM
|
||||
if self.inscription_etat == scu.DEMISSION
|
||||
else sco_codes.DEF,
|
||||
(
|
||||
sco_codes.DEM
|
||||
if self.inscription_etat == scu.DEMISSION
|
||||
else sco_codes.DEF
|
||||
),
|
||||
# propose aussi d'autres codes, au cas où...
|
||||
sco_codes.DEM
|
||||
if self.inscription_etat != scu.DEMISSION
|
||||
else sco_codes.DEF,
|
||||
(
|
||||
sco_codes.DEM
|
||||
if self.inscription_etat != scu.DEMISSION
|
||||
else sco_codes.DEF
|
||||
),
|
||||
sco_codes.ABAN,
|
||||
sco_codes.ABL,
|
||||
sco_codes.EXCLU,
|
||||
@ -595,11 +599,9 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
# Ordonne par numéro d'UE
|
||||
niv_rcue = sorted(
|
||||
self.rcue_by_niveau.items(),
|
||||
key=lambda x: x[1].ue_1.numero
|
||||
if x[1].ue_1
|
||||
else x[1].ue_2.numero
|
||||
if x[1].ue_2
|
||||
else 0,
|
||||
key=lambda x: (
|
||||
x[1].ue_1.numero if x[1].ue_1 else x[1].ue_2.numero if x[1].ue_2 else 0
|
||||
),
|
||||
)
|
||||
return {
|
||||
niveau_id: DecisionsProposeesRCUE(self, rcue, self.inscription_etat)
|
||||
@ -816,9 +818,15 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
||||
Return: True si au moins un code modifié et enregistré.
|
||||
"""
|
||||
modif = False
|
||||
# Vérification notes en attente dans formsemestre origine
|
||||
if only_validantes and self.has_notes_en_attente():
|
||||
return False
|
||||
if only_validantes:
|
||||
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
|
||||
|
||||
# Toujours valider dans l'ordre UE, RCUE, Année
|
||||
annee_scolaire = self.formsemestre.annee_scolaire()
|
||||
@ -1488,9 +1496,11 @@ class DecisionsProposeesUE(DecisionsProposees):
|
||||
self.validation = None # cache toute validation
|
||||
self.explanation = "non inscrit (dem. ou déf.)"
|
||||
self.codes = [
|
||||
sco_codes.DEM
|
||||
if res.get_etud_etat(etud.id) == scu.DEMISSION
|
||||
else sco_codes.DEF
|
||||
(
|
||||
sco_codes.DEM
|
||||
if res.get_etud_etat(etud.id) == scu.DEMISSION
|
||||
else sco_codes.DEF
|
||||
)
|
||||
]
|
||||
return
|
||||
|
||||
|
@ -488,6 +488,29 @@ class Evaluation(models.ScoDocModel):
|
||||
"""
|
||||
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):
|
||||
"""Poids des évaluations (BUT)
|
||||
@ -657,3 +680,6 @@ def _moduleimpl_evaluation_insert_before(
|
||||
db.session.add(e)
|
||||
db.session.commit()
|
||||
return n
|
||||
|
||||
|
||||
from app.models.moduleimpls import ModuleImpl, ModuleImplInscription
|
||||
|
@ -34,7 +34,7 @@ from flask import url_for, flash, g, request
|
||||
from flask_login import current_user
|
||||
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.sco_utils as scu
|
||||
from app import db, log
|
||||
@ -232,7 +232,9 @@ def formsemestre_validation_etud_form(
|
||||
H.append(
|
||||
tf_error_message(
|
||||
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",
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
|
||||
}">tableau de bord</a>)
|
||||
@ -241,6 +243,26 @@ def formsemestre_validation_etud_form(
|
||||
)
|
||||
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
|
||||
if not Se.prev:
|
||||
if Se.sem["semestre_id"] == 1:
|
||||
|
@ -3391,14 +3391,24 @@ li.tf-msg {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.warning {
|
||||
font-weight: bold;
|
||||
.warning, .warning-bloquant {
|
||||
color: red;
|
||||
margin-left: 16px;
|
||||
margin-bottom: 8px;
|
||||
min-width: var(--sco-content-min-width);
|
||||
max-width: var(--sco-content-max-width);
|
||||
}
|
||||
|
||||
.warning::before {
|
||||
content: url(/ScoDoc/static/icons/warning_img.png);
|
||||
vertical-align: -80%;
|
||||
content:"";
|
||||
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 {
|
||||
@ -3411,6 +3421,19 @@ li.tf-msg {
|
||||
/* EMO_WARNING, "⚠️" */
|
||||
}
|
||||
|
||||
.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 {
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
|
1
app/static/icons/warning_bloquant.svg
Normal file
1
app/static/icons/warning_bloquant.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 8.5 KiB |
1
app/static/icons/warning_std.svg
Normal file
1
app/static/icons/warning_std.svg
Normal 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 |
@ -2408,6 +2408,12 @@ def formsemestre_validation_but(
|
||||
)
|
||||
|
||||
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 not read_only:
|
||||
deca.record_form(request.form)
|
||||
@ -2452,9 +2458,21 @@ def formsemestre_validation_but(
|
||||
etat_ins = scu.ETATS_INSCRIPTION.get(inscription.etat, "inconnu?")
|
||||
warning += f"""<div class="warning">{etat_ins} en S{deca.formsemestre_pair.semestre_id}</div>"""
|
||||
|
||||
if deca.has_notes_en_attente():
|
||||
warning += f"""<div class="warning">{etud.nomprenom} a des notes en ATTente.
|
||||
Vous devriez régler cela avant de statuer en jury !</div>"""
|
||||
if has_notes_en_attente:
|
||||
warning += f"""<div class="warning-bloquant">{etud.nomprenom} a des notes en ATTente.
|
||||
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(
|
||||
f"""
|
||||
<div>
|
||||
|
Loading…
Reference in New Issue
Block a user