forked from ScoDoc/ScoDoc
Evaluations bloquées jusqu'à une date. Implements #858
This commit is contained in:
parent
41944bcd29
commit
1c01d987be
@ -291,15 +291,19 @@ class BulletinBUT:
|
|||||||
"date_fin": e.date_fin.isoformat() if e.date_fin else None,
|
"date_fin": e.date_fin.isoformat() if e.date_fin else None,
|
||||||
"description": e.description,
|
"description": e.description,
|
||||||
"evaluation_type": e.evaluation_type,
|
"evaluation_type": e.evaluation_type,
|
||||||
"note": {
|
"note": (
|
||||||
"value": fmt_note(
|
{
|
||||||
eval_notes[etud.id],
|
"value": fmt_note(
|
||||||
note_max=e.note_max,
|
eval_notes[etud.id],
|
||||||
),
|
note_max=e.note_max,
|
||||||
"min": fmt_note(notes_ok.min(), note_max=e.note_max),
|
),
|
||||||
"max": fmt_note(notes_ok.max(), note_max=e.note_max),
|
"min": fmt_note(notes_ok.min(), note_max=e.note_max),
|
||||||
"moy": fmt_note(notes_ok.mean(), note_max=e.note_max),
|
"max": fmt_note(notes_ok.max(), note_max=e.note_max),
|
||||||
},
|
"moy": fmt_note(notes_ok.mean(), note_max=e.note_max),
|
||||||
|
}
|
||||||
|
if not e.is_blocked()
|
||||||
|
else {}
|
||||||
|
),
|
||||||
"poids": poids,
|
"poids": poids,
|
||||||
"url": (
|
"url": (
|
||||||
url_for(
|
url_for(
|
||||||
|
@ -35,7 +35,6 @@ moyenne générale d'une UE.
|
|||||||
"""
|
"""
|
||||||
import dataclasses
|
import dataclasses
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
@ -151,16 +150,18 @@ class ModuleImplResults:
|
|||||||
self.evaluations_completes_dict = {}
|
self.evaluations_completes_dict = {}
|
||||||
for evaluation in moduleimpl.evaluations:
|
for evaluation in moduleimpl.evaluations:
|
||||||
eval_df = self._load_evaluation_notes(evaluation)
|
eval_df = self._load_evaluation_notes(evaluation)
|
||||||
# is_complete ssi tous les inscrits (non dem) au semestre ont une note
|
# is_complete ssi
|
||||||
# ou évaluation déclarée "à prise en compte immédiate"
|
# tous les inscrits (non dem) au module ont une note
|
||||||
# Les évaluations de rattrapage et 2eme session sont toujours complètes
|
# ou évaluation déclarée "à prise en compte immédiate"
|
||||||
|
# ou rattrapage, 2eme session, bonus
|
||||||
|
# ET pas bloquée par date (is_blocked)
|
||||||
|
|
||||||
etudids_sans_note = inscrits_module - set(eval_df.index) # sans les dem.
|
etudids_sans_note = inscrits_module - set(eval_df.index) # sans les dem.
|
||||||
is_complete = (
|
is_complete = (
|
||||||
(evaluation.evaluation_type != Evaluation.EVALUATION_NORMALE)
|
(evaluation.evaluation_type != Evaluation.EVALUATION_NORMALE)
|
||||||
or (evaluation.publish_incomplete)
|
or (evaluation.publish_incomplete)
|
||||||
or (not etudids_sans_note)
|
or (not etudids_sans_note)
|
||||||
)
|
) and not evaluation.is_blocked()
|
||||||
self.evaluations_completes.append(is_complete)
|
self.evaluations_completes.append(is_complete)
|
||||||
self.evaluations_completes_dict[evaluation.id] = is_complete
|
self.evaluations_completes_dict[evaluation.id] = is_complete
|
||||||
self.evals_etudids_sans_note[evaluation.id] = etudids_sans_note
|
self.evals_etudids_sans_note[evaluation.id] = etudids_sans_note
|
||||||
@ -185,7 +186,7 @@ class ModuleImplResults:
|
|||||||
].index
|
].index
|
||||||
)
|
)
|
||||||
if evaluation.publish_incomplete:
|
if evaluation.publish_incomplete:
|
||||||
# et en "imédiat", tous ceux sans note
|
# et en "immédiat", tous ceux sans note
|
||||||
eval_etudids_attente |= etudids_sans_note
|
eval_etudids_attente |= etudids_sans_note
|
||||||
# Synthèse pour état du module:
|
# Synthèse pour état du module:
|
||||||
self.etudids_attente |= eval_etudids_attente
|
self.etudids_attente |= eval_etudids_attente
|
||||||
@ -276,7 +277,7 @@ class ModuleImplResults:
|
|||||||
) / [e.note_max / 20.0 for e in moduleimpl.evaluations]
|
) / [e.note_max / 20.0 for e in moduleimpl.evaluations]
|
||||||
|
|
||||||
def get_eval_notes_dict(self, evaluation_id: int) -> dict:
|
def get_eval_notes_dict(self, evaluation_id: int) -> dict:
|
||||||
"""Notes d'une évaulation, brutes, sous forme d'un dict
|
"""Notes d'une évaluation, brutes, sous forme d'un dict
|
||||||
{ etudid : valeur }
|
{ etudid : valeur }
|
||||||
avec les valeurs float, ou "ABS" ou EXC
|
avec les valeurs float, ou "ABS" ou EXC
|
||||||
"""
|
"""
|
||||||
|
@ -230,8 +230,8 @@ class ResultatsSemestre(ResultatsCache):
|
|||||||
date_modif = cursor.one_or_none()
|
date_modif = cursor.one_or_none()
|
||||||
last_modif = date_modif[0] if date_modif else None
|
last_modif = date_modif[0] if date_modif else None
|
||||||
return {
|
return {
|
||||||
"coefficient": evaluation.coefficient or 0.0,
|
"coefficient": evaluation.coefficient,
|
||||||
"description": evaluation.description or "",
|
"description": evaluation.description,
|
||||||
"evaluation_id": evaluation.id,
|
"evaluation_id": evaluation.id,
|
||||||
"jour": evaluation.date_debut or datetime.datetime(1900, 1, 1),
|
"jour": evaluation.date_debut or datetime.datetime(1900, 1, 1),
|
||||||
"etat": {
|
"etat": {
|
||||||
|
@ -10,6 +10,7 @@ from flask_login import current_user
|
|||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from app import db, log
|
from app import db, log
|
||||||
|
from app import models
|
||||||
from app.models.etudiants import Identite
|
from app.models.etudiants import Identite
|
||||||
from app.models.events import ScolarNews
|
from app.models.events import ScolarNews
|
||||||
from app.models.notes import NotesNotes
|
from app.models.notes import NotesNotes
|
||||||
@ -24,7 +25,7 @@ NOON = datetime.time(12, 00)
|
|||||||
DEFAULT_EVALUATION_TIME = datetime.time(8, 0)
|
DEFAULT_EVALUATION_TIME = datetime.time(8, 0)
|
||||||
|
|
||||||
|
|
||||||
class Evaluation(db.Model):
|
class Evaluation(models.ScoDocModel):
|
||||||
"""Evaluation (contrôle, examen, ...)"""
|
"""Evaluation (contrôle, examen, ...)"""
|
||||||
|
|
||||||
__tablename__ = "notes_evaluation"
|
__tablename__ = "notes_evaluation"
|
||||||
@ -36,9 +37,9 @@ class Evaluation(db.Model):
|
|||||||
)
|
)
|
||||||
date_debut = db.Column(db.DateTime(timezone=True), nullable=True)
|
date_debut = db.Column(db.DateTime(timezone=True), nullable=True)
|
||||||
date_fin = db.Column(db.DateTime(timezone=True), nullable=True)
|
date_fin = db.Column(db.DateTime(timezone=True), nullable=True)
|
||||||
description = db.Column(db.Text)
|
description = db.Column(db.Text, nullable=False)
|
||||||
note_max = db.Column(db.Float)
|
note_max = db.Column(db.Float, nullable=False)
|
||||||
coefficient = db.Column(db.Float)
|
coefficient = db.Column(db.Float, nullable=False)
|
||||||
visibulletin = db.Column(
|
visibulletin = db.Column(
|
||||||
db.Boolean, nullable=False, default=True, server_default="true"
|
db.Boolean, nullable=False, default=True, server_default="true"
|
||||||
)
|
)
|
||||||
@ -46,10 +47,14 @@ class Evaluation(db.Model):
|
|||||||
publish_incomplete = db.Column(
|
publish_incomplete = db.Column(
|
||||||
db.Boolean, nullable=False, default=False, server_default="false"
|
db.Boolean, nullable=False, default=False, server_default="false"
|
||||||
)
|
)
|
||||||
# type d'evaluation: 0 normale, 1 rattrapage, 2 "2eme session"
|
"prise en compte immédiate"
|
||||||
evaluation_type = db.Column(
|
evaluation_type = db.Column(
|
||||||
db.Integer, nullable=False, default=0, server_default="0"
|
db.Integer, nullable=False, default=0, server_default="0"
|
||||||
)
|
)
|
||||||
|
"type d'evaluation: 0 normale, 1 rattrapage, 2 2eme session, 3 bonus"
|
||||||
|
blocked_until = db.Column(db.DateTime(timezone=True), nullable=True)
|
||||||
|
"date de prise en compte"
|
||||||
|
BLOCKED_FOREVER = datetime.datetime(2666, 12, 31, tzinfo=scu.TIME_ZONE)
|
||||||
# ordre de presentation (par défaut, le plus petit numero
|
# ordre de presentation (par défaut, le plus petit numero
|
||||||
# est la plus ancienne eval):
|
# est la plus ancienne eval):
|
||||||
numero = db.Column(db.Integer, nullable=False, default=0)
|
numero = db.Column(db.Integer, nullable=False, default=0)
|
||||||
@ -79,6 +84,7 @@ class Evaluation(db.Model):
|
|||||||
date_fin: datetime.datetime = None,
|
date_fin: datetime.datetime = None,
|
||||||
description=None,
|
description=None,
|
||||||
note_max=None,
|
note_max=None,
|
||||||
|
blocked_until=None,
|
||||||
coefficient=None,
|
coefficient=None,
|
||||||
visibulletin=None,
|
visibulletin=None,
|
||||||
publish_incomplete=None,
|
publish_incomplete=None,
|
||||||
@ -208,6 +214,10 @@ class Evaluation(db.Model):
|
|||||||
def to_dict_api(self) -> dict:
|
def to_dict_api(self) -> dict:
|
||||||
"Représentation dict pour API JSON"
|
"Représentation dict pour API JSON"
|
||||||
return {
|
return {
|
||||||
|
"blocked": self.is_blocked(),
|
||||||
|
"blocked_until": (
|
||||||
|
self.blocked_until.isoformat() if self.blocked_until else ""
|
||||||
|
),
|
||||||
"coefficient": self.coefficient,
|
"coefficient": self.coefficient,
|
||||||
"date_debut": self.date_debut.isoformat() if self.date_debut else "",
|
"date_debut": self.date_debut.isoformat() if self.date_debut else "",
|
||||||
"date_fin": self.date_fin.isoformat() if self.date_fin else "",
|
"date_fin": self.date_fin.isoformat() if self.date_fin else "",
|
||||||
@ -244,14 +254,14 @@ class Evaluation(db.Model):
|
|||||||
|
|
||||||
return e_dict
|
return e_dict
|
||||||
|
|
||||||
def from_dict(self, data):
|
def convert_dict_fields(self, args: dict) -> dict:
|
||||||
"""Set evaluation attributes from given dict values."""
|
"""Convert fields in the given dict. No other side effect.
|
||||||
check_convert_evaluation_args(self.moduleimpl, data)
|
returns: dict to store in model's db.
|
||||||
if data.get("numero") is None:
|
"""
|
||||||
data["numero"] = Evaluation.get_max_numero(self.moduleimpl.id) + 1
|
check_convert_evaluation_args(self.moduleimpl, args)
|
||||||
for k in self.__dict__:
|
if args.get("numero") is None:
|
||||||
if k != "_sa_instance_state" and k != "id" and k in data:
|
args["numero"] = Evaluation.get_max_numero(self.moduleimpl.id) + 1
|
||||||
setattr(self, k, data[k])
|
return args
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_evaluation(
|
def get_evaluation(
|
||||||
@ -370,19 +380,6 @@ class Evaluation(db.Model):
|
|||||||
Chaine vide si non renseignée."""
|
Chaine vide si non renseignée."""
|
||||||
return self.date_fin.time().isoformat("minutes") if self.date_fin else ""
|
return self.date_fin.time().isoformat("minutes") if self.date_fin else ""
|
||||||
|
|
||||||
def clone(self, not_copying=()):
|
|
||||||
"""Clone, not copying the given attrs
|
|
||||||
Attention: la copie n'a pas d'id avant le prochain commit
|
|
||||||
"""
|
|
||||||
d = dict(self.__dict__)
|
|
||||||
d.pop("id") # get rid of id
|
|
||||||
d.pop("_sa_instance_state") # get rid of SQLAlchemy special attr
|
|
||||||
for k in not_copying:
|
|
||||||
d.pop(k)
|
|
||||||
copy = self.__class__(**d)
|
|
||||||
db.session.add(copy)
|
|
||||||
return copy
|
|
||||||
|
|
||||||
def is_matin(self) -> bool:
|
def is_matin(self) -> bool:
|
||||||
"Evaluation commençant le matin (faux si pas de date)"
|
"Evaluation commençant le matin (faux si pas de date)"
|
||||||
if not self.date_debut:
|
if not self.date_debut:
|
||||||
@ -395,6 +392,14 @@ class Evaluation(db.Model):
|
|||||||
return False
|
return False
|
||||||
return self.date_debut.time() >= NOON
|
return self.date_debut.time() >= NOON
|
||||||
|
|
||||||
|
def is_blocked(self, now=None) -> bool:
|
||||||
|
"True si prise en compte bloquée"
|
||||||
|
if self.blocked_until is None:
|
||||||
|
return False
|
||||||
|
if now is None:
|
||||||
|
now = datetime.datetime.now(scu.TIME_ZONE)
|
||||||
|
return self.blocked_until > now
|
||||||
|
|
||||||
def set_default_poids(self) -> bool:
|
def set_default_poids(self) -> bool:
|
||||||
"""Initialize les poids vers les UE à leurs valeurs par défaut
|
"""Initialize les poids vers les UE à leurs valeurs par défaut
|
||||||
C'est à dire à 1 si le coef. module/UE est non nul, 0 sinon.
|
C'est à dire à 1 si le coef. module/UE est non nul, 0 sinon.
|
||||||
@ -621,6 +626,8 @@ def check_convert_evaluation_args(moduleimpl: "ModuleImpl", data: dict):
|
|||||||
"Heures de l'évaluation incohérentes !",
|
"Heures de l'évaluation incohérentes !",
|
||||||
dest_url="javascript:history.back();",
|
dest_url="javascript:history.back();",
|
||||||
)
|
)
|
||||||
|
if "blocked_until" in data:
|
||||||
|
data["blocked_until"] = data["blocked_until"] or None
|
||||||
|
|
||||||
|
|
||||||
def heure_to_time(heure: str) -> datetime.time:
|
def heure_to_time(heure: str) -> datetime.time:
|
||||||
|
@ -93,6 +93,10 @@ class FormSemestre(db.Model):
|
|||||||
db.Boolean(), nullable=False, default=False, server_default="false"
|
db.Boolean(), nullable=False, default=False, server_default="false"
|
||||||
)
|
)
|
||||||
"Si vrai, la moyenne générale indicative BUT n'est pas calculée"
|
"Si vrai, la moyenne générale indicative BUT n'est pas calculée"
|
||||||
|
mode_calcul_moyennes = db.Column(
|
||||||
|
db.Integer, nullable=False, default=0, server_default="0"
|
||||||
|
)
|
||||||
|
"pour usage futur"
|
||||||
gestion_semestrielle = db.Column(
|
gestion_semestrielle = db.Column(
|
||||||
db.Boolean(), nullable=False, default=False, server_default="false"
|
db.Boolean(), nullable=False, default=False, server_default="false"
|
||||||
)
|
)
|
||||||
|
@ -318,7 +318,7 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
|
|||||||
if nt.bonus_ues is not None:
|
if nt.bonus_ues is not None:
|
||||||
u["cur_moy_ue_txt"] += " (+ues)"
|
u["cur_moy_ue_txt"] += " (+ues)"
|
||||||
u["moy_ue_txt"] = scu.fmt_note(ue_status["moy"])
|
u["moy_ue_txt"] = scu.fmt_note(ue_status["moy"])
|
||||||
if ue_status["coef_ue"] != None:
|
if ue_status["coef_ue"] is not None:
|
||||||
u["coef_ue_txt"] = scu.fmt_coef(ue_status["coef_ue"])
|
u["coef_ue_txt"] = scu.fmt_coef(ue_status["coef_ue"])
|
||||||
else:
|
else:
|
||||||
u["coef_ue_txt"] = "-"
|
u["coef_ue_txt"] = "-"
|
||||||
@ -558,6 +558,8 @@ def _ue_mod_bulletin(
|
|||||||
).order_by(Evaluation.numero, Evaluation.date_debut)
|
).order_by(Evaluation.numero, Evaluation.date_debut)
|
||||||
# (plus ancienne d'abord)
|
# (plus ancienne d'abord)
|
||||||
for e in all_evals:
|
for e in all_evals:
|
||||||
|
if e.is_blocked():
|
||||||
|
continue # ignore évaluations bloquées
|
||||||
if not e.visibulletin and version != "long":
|
if not e.visibulletin and version != "long":
|
||||||
continue
|
continue
|
||||||
is_complete = e.id in complete_eval_ids
|
is_complete = e.id in complete_eval_ids
|
||||||
@ -625,7 +627,7 @@ def _ue_mod_bulletin(
|
|||||||
)
|
)
|
||||||
):
|
):
|
||||||
# ne liste pas les eval malus sans notes
|
# ne liste pas les eval malus sans notes
|
||||||
# ni les rattrapages et sessions 2 si pas de note
|
# ni les rattrapages, sessions 2 et bonus si pas de note
|
||||||
if e.id in complete_eval_ids:
|
if e.id in complete_eval_ids:
|
||||||
mod["evaluations"].append(e_dict)
|
mod["evaluations"].append(e_dict)
|
||||||
else:
|
else:
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
"""Génération du bulletin en format JSON
|
"""Génération du bulletin en format JSON (formations classiques)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -108,7 +108,7 @@ def evaluation_create_form(
|
|||||||
raise ValueError("missing evaluation_id parameter")
|
raise ValueError("missing evaluation_id parameter")
|
||||||
initvalues = evaluation.to_dict()
|
initvalues = evaluation.to_dict()
|
||||||
moduleimpl_id = initvalues["moduleimpl_id"]
|
moduleimpl_id = initvalues["moduleimpl_id"]
|
||||||
submitlabel = "Modifier les données"
|
submitlabel = "Modifier l'évaluation"
|
||||||
action = "Modification d'une évaluation"
|
action = "Modification d'une évaluation"
|
||||||
link = ""
|
link = ""
|
||||||
# Note maximale actuelle dans cette éval ?
|
# Note maximale actuelle dans cette éval ?
|
||||||
@ -142,6 +142,15 @@ def evaluation_create_form(
|
|||||||
else:
|
else:
|
||||||
poids = 0.0
|
poids = 0.0
|
||||||
initvalues[f"poids_{ue.id}"] = poids
|
initvalues[f"poids_{ue.id}"] = poids
|
||||||
|
# Blocage
|
||||||
|
if edit:
|
||||||
|
initvalues["blocked"] = evaluation.is_blocked()
|
||||||
|
initvalues["blocked_until"] = (
|
||||||
|
evaluation.blocked_until.strftime("%d/%m/%Y")
|
||||||
|
if evaluation.blocked_until
|
||||||
|
and evaluation.blocked_until < Evaluation.BLOCKED_FOREVER
|
||||||
|
else ""
|
||||||
|
)
|
||||||
#
|
#
|
||||||
form = [
|
form = [
|
||||||
("evaluation_id", {"default": evaluation_id, "input_type": "hidden"}),
|
("evaluation_id", {"default": evaluation_id, "input_type": "hidden"}),
|
||||||
@ -260,6 +269,7 @@ def evaluation_create_form(
|
|||||||
"explanation": """importance de l'évaluation (multiplie les poids ci-dessous).
|
"explanation": """importance de l'évaluation (multiplie les poids ci-dessous).
|
||||||
Non utilisé pour les bonus.""",
|
Non utilisé pour les bonus.""",
|
||||||
"allow_null": False,
|
"allow_null": False,
|
||||||
|
"dom_id": "evaluation-edit-coef",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
@ -301,6 +311,28 @@ def evaluation_create_form(
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
# Bloquage / date prise en compte
|
||||||
|
form += [
|
||||||
|
(
|
||||||
|
"blocked",
|
||||||
|
{
|
||||||
|
"input_type": "boolcheckbox",
|
||||||
|
"title": "Bloquer la prise en compte",
|
||||||
|
"explanation": """empêche la prise en compte
|
||||||
|
(ne sera pas visible sur les bulletins ni dans les tableaux)""",
|
||||||
|
"dom_id": "evaluation-edit-blocked",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"blocked_until",
|
||||||
|
{
|
||||||
|
"input_type": "datedmy",
|
||||||
|
"title": "Date déblocage",
|
||||||
|
"size": 12,
|
||||||
|
"explanation": "sera débloquée à partir de cette date",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
tf = TrivialFormulator(
|
tf = TrivialFormulator(
|
||||||
request.base_url,
|
request.base_url,
|
||||||
vals,
|
vals,
|
||||||
@ -331,7 +363,9 @@ def evaluation_create_form(
|
|||||||
+ "\n".join(H)
|
+ "\n".join(H)
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ tf[1]
|
+ tf[1]
|
||||||
+ render_template("scodoc/help/evaluations.j2", is_apc=is_apc)
|
+ render_template(
|
||||||
|
"scodoc/help/evaluations.j2", is_apc=is_apc, modimpl=modimpl
|
||||||
|
)
|
||||||
+ render_template("sco_timepicker.j2")
|
+ render_template("sco_timepicker.j2")
|
||||||
+ html_sco_header.sco_footer()
|
+ html_sco_header.sco_footer()
|
||||||
)
|
)
|
||||||
@ -357,7 +391,8 @@ def evaluation_create_form(
|
|||||||
raise ScoValueError("Heure début invalide") from exc
|
raise ScoValueError("Heure début invalide") from exc
|
||||||
args["date_debut"] = datetime.datetime.combine(date_debut, heure_debut)
|
args["date_debut"] = datetime.datetime.combine(date_debut, heure_debut)
|
||||||
args.pop("heure_debut", None)
|
args.pop("heure_debut", None)
|
||||||
# note: ce formulaire ne permet de créer que des évaluation avec debut et fin sur le même jour.
|
# note: ce formulaire ne permet de créer que des évaluations
|
||||||
|
# avec debut et fin sur le même jour.
|
||||||
if date_debut and args.get("heure_fin"):
|
if date_debut and args.get("heure_fin"):
|
||||||
try:
|
try:
|
||||||
heure_fin = heure_to_time(args["heure_fin"])
|
heure_fin = heure_to_time(args["heure_fin"])
|
||||||
@ -365,6 +400,19 @@ def evaluation_create_form(
|
|||||||
raise ScoValueError("Heure fin invalide") from exc
|
raise ScoValueError("Heure fin invalide") from exc
|
||||||
args["date_fin"] = datetime.datetime.combine(date_debut, heure_fin)
|
args["date_fin"] = datetime.datetime.combine(date_debut, heure_fin)
|
||||||
args.pop("heure_fin", None)
|
args.pop("heure_fin", None)
|
||||||
|
# Blocage:
|
||||||
|
if args.get("blocked"):
|
||||||
|
if args.get("blocked_until"):
|
||||||
|
try:
|
||||||
|
args["blocked_until"] = datetime.datetime.strptime(
|
||||||
|
args["blocked_until"], "%d/%m/%Y"
|
||||||
|
)
|
||||||
|
except ValueError as exc:
|
||||||
|
raise ScoValueError("Date déblocage (j/m/a) invalide") from exc
|
||||||
|
else: # bloquage coché sans date
|
||||||
|
args["blocked_until"] = Evaluation.BLOCKED_FOREVER
|
||||||
|
else: # si pas coché, efface date déblocage
|
||||||
|
args["blocked_until"] = None
|
||||||
#
|
#
|
||||||
if edit:
|
if edit:
|
||||||
evaluation.from_dict(args)
|
evaluation.from_dict(args)
|
||||||
|
@ -40,7 +40,7 @@ from app import db
|
|||||||
from app.auth.models import User
|
from app.auth.models import User
|
||||||
from app.comp import res_sem
|
from app.comp import res_sem
|
||||||
from app.comp.res_compat import NotesTableCompat
|
from app.comp.res_compat import NotesTableCompat
|
||||||
from app.models import Evaluation, FormSemestre, ModuleImpl
|
from app.models import Evaluation, FormSemestre, ModuleImpl, Module
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc.sco_utils import ModuleType
|
from app.scodoc.sco_utils import ModuleType
|
||||||
@ -48,7 +48,6 @@ from app.scodoc.gen_tables import GenTable
|
|||||||
from app.scodoc import html_sco_header
|
from app.scodoc import html_sco_header
|
||||||
from app.scodoc import sco_cal
|
from app.scodoc import sco_cal
|
||||||
from app.scodoc import sco_evaluation_db
|
from app.scodoc import sco_evaluation_db
|
||||||
from app.scodoc import sco_edit_module
|
|
||||||
from app.scodoc import sco_formsemestre_inscriptions
|
from app.scodoc import sco_formsemestre_inscriptions
|
||||||
from app.scodoc import sco_groups
|
from app.scodoc import sco_groups
|
||||||
from app.scodoc import sco_moduleimpl
|
from app.scodoc import sco_moduleimpl
|
||||||
@ -113,6 +112,7 @@ def do_evaluation_etat(
|
|||||||
nb_neutre,
|
nb_neutre,
|
||||||
nb_att,
|
nb_att,
|
||||||
moy, median, mini, maxi : # notes, en chaine, sur 20
|
moy, median, mini, maxi : # notes, en chaine, sur 20
|
||||||
|
maxi_num : note max, numérique
|
||||||
last_modif: datetime, *
|
last_modif: datetime, *
|
||||||
gr_complets, gr_incomplets,
|
gr_complets, gr_incomplets,
|
||||||
evalcomplete *
|
evalcomplete *
|
||||||
@ -129,11 +129,12 @@ def do_evaluation_etat(
|
|||||||
) # { etudid : note }
|
) # { etudid : note }
|
||||||
|
|
||||||
# ---- Liste des groupes complets et incomplets
|
# ---- Liste des groupes complets et incomplets
|
||||||
E = sco_evaluation_db.get_evaluations_dict(args={"evaluation_id": evaluation_id})[0]
|
evaluation = Evaluation.get_evaluation(evaluation_id)
|
||||||
M = sco_moduleimpl.moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0]
|
modimpl: ModuleImpl = evaluation.moduleimpl
|
||||||
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0]
|
module: Module = modimpl.module
|
||||||
is_malus = Mod["module_type"] == ModuleType.MALUS # True si module de malus
|
|
||||||
formsemestre_id = M["formsemestre_id"]
|
is_malus = module.module_type == ModuleType.MALUS # True si module de malus
|
||||||
|
formsemestre_id = modimpl.formsemestre_id
|
||||||
# Si partition_id is None, prend 'all' ou bien la premiere:
|
# Si partition_id is None, prend 'all' ou bien la premiere:
|
||||||
if partition_id is None:
|
if partition_id is None:
|
||||||
if select_first_partition:
|
if select_first_partition:
|
||||||
@ -149,9 +150,7 @@ def do_evaluation_etat(
|
|||||||
insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(
|
insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits(
|
||||||
formsemestre_id
|
formsemestre_id
|
||||||
)
|
)
|
||||||
insmod = sco_moduleimpl.do_moduleimpl_inscription_list(
|
insmod = sco_moduleimpl.do_moduleimpl_inscription_list(moduleimpl_id=modimpl.id)
|
||||||
moduleimpl_id=E["moduleimpl_id"]
|
|
||||||
)
|
|
||||||
insmodset = {x["etudid"] for x in insmod}
|
insmodset = {x["etudid"] for x in insmod}
|
||||||
# retire de insem ceux qui ne sont pas inscrits au module
|
# retire de insem ceux qui ne sont pas inscrits au module
|
||||||
ins = [i for i in insem if i["etudid"] in insmodset]
|
ins = [i for i in insem if i["etudid"] in insmodset]
|
||||||
@ -174,9 +173,9 @@ def do_evaluation_etat(
|
|||||||
maxi_num = None
|
maxi_num = None
|
||||||
else:
|
else:
|
||||||
median = scu.fmt_note(median_num)
|
median = scu.fmt_note(median_num)
|
||||||
moy = scu.fmt_note(moy_num, E["note_max"])
|
moy = scu.fmt_note(moy_num, evaluation.note_max)
|
||||||
mini = scu.fmt_note(mini_num, E["note_max"])
|
mini = scu.fmt_note(mini_num, evaluation.note_max)
|
||||||
maxi = scu.fmt_note(maxi_num, E["note_max"])
|
maxi = scu.fmt_note(maxi_num, evaluation.note_max)
|
||||||
# cherche date derniere modif note
|
# cherche date derniere modif note
|
||||||
if len(etuds_notes_dict):
|
if len(etuds_notes_dict):
|
||||||
t = [x["date"] for x in etuds_notes_dict.values()]
|
t = [x["date"] for x in etuds_notes_dict.values()]
|
||||||
@ -218,14 +217,16 @@ def do_evaluation_etat(
|
|||||||
gr_incomplets = list(group_nb_missing.keys())
|
gr_incomplets = list(group_nb_missing.keys())
|
||||||
gr_incomplets.sort()
|
gr_incomplets.sort()
|
||||||
|
|
||||||
complete = (total_nb_missing == 0) or (
|
complete = (
|
||||||
E["evaluation_type"] != Evaluation.EVALUATION_NORMALE
|
(total_nb_missing == 0)
|
||||||
|
or (evaluation.evaluation_type != Evaluation.EVALUATION_NORMALE)
|
||||||
|
and not evaluation.is_blocked()
|
||||||
)
|
)
|
||||||
evalattente = (total_nb_missing > 0) and (
|
evalattente = (total_nb_missing > 0) and (
|
||||||
(total_nb_missing == total_nb_att) or E["publish_incomplete"]
|
(total_nb_missing == total_nb_att) or evaluation.publish_incomplete
|
||||||
)
|
)
|
||||||
# mais ne met pas en attente les evals immediates sans aucune notes:
|
# mais ne met pas en attente les evals immediates sans aucune notes:
|
||||||
if E["publish_incomplete"] and nb_notes == 0:
|
if evaluation.publish_incomplete and nb_notes == 0:
|
||||||
evalattente = False
|
evalattente = False
|
||||||
|
|
||||||
# Calcul moyenne dans chaque groupe de TD
|
# Calcul moyenne dans chaque groupe de TD
|
||||||
@ -236,10 +237,10 @@ def do_evaluation_etat(
|
|||||||
{
|
{
|
||||||
"group_id": group_id,
|
"group_id": group_id,
|
||||||
"group_name": group_by_id[group_id]["group_name"],
|
"group_name": group_by_id[group_id]["group_name"],
|
||||||
"gr_moy": scu.fmt_note(gr_moy, E["note_max"]),
|
"gr_moy": scu.fmt_note(gr_moy, evaluation.note_max),
|
||||||
"gr_median": scu.fmt_note(gr_median, E["note_max"]),
|
"gr_median": scu.fmt_note(gr_median, evaluation.note_max),
|
||||||
"gr_mini": scu.fmt_note(gr_mini, E["note_max"]),
|
"gr_mini": scu.fmt_note(gr_mini, evaluation.note_max),
|
||||||
"gr_maxi": scu.fmt_note(gr_maxi, E["note_max"]),
|
"gr_maxi": scu.fmt_note(gr_maxi, evaluation.note_max),
|
||||||
"gr_nb_notes": len(notes),
|
"gr_nb_notes": len(notes),
|
||||||
"gr_nb_att": len([x for x in notes if x == scu.NOTES_ATTENTE]),
|
"gr_nb_att": len([x for x in notes if x == scu.NOTES_ATTENTE]),
|
||||||
}
|
}
|
||||||
|
@ -534,7 +534,7 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line
|
|||||||
# description evaluation
|
# description evaluation
|
||||||
ws.append_single_cell_row(scu.unescape_html(description), style_titres)
|
ws.append_single_cell_row(scu.unescape_html(description), style_titres)
|
||||||
ws.append_single_cell_row(
|
ws.append_single_cell_row(
|
||||||
f"Evaluation {evaluation.descr_date()} (coef. {(evaluation.coefficient or 0.0):g})",
|
f"Evaluation {evaluation.descr_date()} (coef. {(evaluation.coefficient):g})",
|
||||||
style,
|
style,
|
||||||
)
|
)
|
||||||
# ligne blanche
|
# ligne blanche
|
||||||
|
@ -531,6 +531,10 @@ def _ligne_evaluation(
|
|||||||
if not evaluation.visibulletin:
|
if not evaluation.visibulletin:
|
||||||
tr_class += " non_visible_inter"
|
tr_class += " non_visible_inter"
|
||||||
tr_class_1 = "mievr"
|
tr_class_1 = "mievr"
|
||||||
|
if evaluation.is_blocked():
|
||||||
|
tr_class += " evaluation_blocked"
|
||||||
|
tr_class_1 += " evaluation_blocked"
|
||||||
|
|
||||||
if not first_eval:
|
if not first_eval:
|
||||||
H.append("""<tr><td colspan="8"> </td></tr>""")
|
H.append("""<tr><td colspan="8"> </td></tr>""")
|
||||||
tr_class_1 += " mievr_spaced"
|
tr_class_1 += " mievr_spaced"
|
||||||
@ -564,7 +568,7 @@ def _ligne_evaluation(
|
|||||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||||
}" class="mievr_evalnodate">Évaluation sans date</a>"""
|
}" class="mievr_evalnodate">Évaluation sans date</a>"""
|
||||||
)
|
)
|
||||||
H.append(f" <em>{evaluation.description or ''}</em>")
|
H.append(f" <em>{evaluation.description}</em>")
|
||||||
if evaluation.evaluation_type == Evaluation.EVALUATION_RATTRAPAGE:
|
if evaluation.evaluation_type == Evaluation.EVALUATION_RATTRAPAGE:
|
||||||
H.append(
|
H.append(
|
||||||
"""<span class="mievr_rattr" title="remplace si meilleure note">rattrapage</span>"""
|
"""<span class="mievr_rattr" title="remplace si meilleure note">rattrapage</span>"""
|
||||||
@ -611,8 +615,15 @@ def _ligne_evaluation(
|
|||||||
else:
|
else:
|
||||||
H.append(arrow_none)
|
H.append(arrow_none)
|
||||||
|
|
||||||
if etat["evalcomplete"]:
|
if evaluation.is_blocked():
|
||||||
etat_txt = f"""(prise en compte{
|
etat_txt = f"""évaluation bloquée {
|
||||||
|
"jusqu'au " + evaluation.blocked_until.strftime("%d/%m/%Y")
|
||||||
|
if evaluation.blocked_until < Evaluation.BLOCKED_FOREVER
|
||||||
|
else "" }
|
||||||
|
"""
|
||||||
|
etat_descr = """prise en compte bloquée"""
|
||||||
|
elif etat["evalcomplete"]:
|
||||||
|
etat_txt = f"""Moyenne (prise en compte{
|
||||||
""
|
""
|
||||||
if evaluation.visibulletin
|
if evaluation.visibulletin
|
||||||
else ", cachée en intermédiaire"})
|
else ", cachée en intermédiaire"})
|
||||||
@ -621,7 +632,7 @@ def _ligne_evaluation(
|
|||||||
", évaluation cachée sur les bulletins en version intermédiaire et sur la passerelle"
|
", évaluation cachée sur les bulletins en version intermédiaire et sur la passerelle"
|
||||||
}"""
|
}"""
|
||||||
elif etat["evalattente"] and not evaluation.publish_incomplete:
|
elif etat["evalattente"] and not evaluation.publish_incomplete:
|
||||||
etat_txt = "(prise en compte, mais <b>notes en attente</b>)"
|
etat_txt = "Moyenne (prise en compte, mais <b>notes en attente</b>)"
|
||||||
etat_descr = "il y a des notes en attente"
|
etat_descr = "il y a des notes en attente"
|
||||||
elif evaluation.publish_incomplete:
|
elif evaluation.publish_incomplete:
|
||||||
etat_txt = """(prise en compte <b>immédiate</b>)"""
|
etat_txt = """(prise en compte <b>immédiate</b>)"""
|
||||||
@ -629,28 +640,29 @@ def _ligne_evaluation(
|
|||||||
"il manque des notes, mais la prise en compte immédiate a été demandée"
|
"il manque des notes, mais la prise en compte immédiate a été demandée"
|
||||||
)
|
)
|
||||||
elif etat["nb_notes"] != 0:
|
elif etat["nb_notes"] != 0:
|
||||||
etat_txt = "(<b>non</b> prise en compte)"
|
etat_txt = "Moyenne (<b>non</b> prise en compte)"
|
||||||
etat_descr = "il manque des notes"
|
etat_descr = "il manque des notes"
|
||||||
else:
|
else:
|
||||||
etat_txt = ""
|
etat_txt = ""
|
||||||
if can_edit_evals and etat_txt:
|
if etat_txt:
|
||||||
etat_txt = f"""<a href="{ url_for("notes.evaluation_edit",
|
if can_edit_evals:
|
||||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
etat_txt = f"""<a href="{ url_for("notes.evaluation_edit",
|
||||||
}" title="{etat_descr}">{etat_txt}</a>"""
|
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||||
|
}" title="{etat_descr}">{etat_txt}</a>"""
|
||||||
|
|
||||||
H.append(
|
H.append(
|
||||||
f"""</span></span></td>
|
f"""</span></span></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="{tr_class}">
|
<tr class="{tr_class} mievr_in">
|
||||||
<th class="moduleimpl_evaluations" colspan="2"> </th>
|
<th class="moduleimpl_evaluations" colspan="2"> </th>
|
||||||
<th class="moduleimpl_evaluations">Durée</th>
|
<th class="moduleimpl_evaluations">Durée</th>
|
||||||
<th class="moduleimpl_evaluations">Coef.</th>
|
<th class="moduleimpl_evaluations">Coef.</th>
|
||||||
<th class="moduleimpl_evaluations">Notes</th>
|
<th class="moduleimpl_evaluations">Notes</th>
|
||||||
<th class="moduleimpl_evaluations">Abs</th>
|
<th class="moduleimpl_evaluations">Abs</th>
|
||||||
<th class="moduleimpl_evaluations">N</th>
|
<th class="moduleimpl_evaluations">N</th>
|
||||||
<th class="moduleimpl_evaluations" colspan="2">Moyenne {etat_txt}</th>
|
<th class="moduleimpl_evaluations moduleimpl_evaluation_moy" colspan="2"><span>{etat_txt}</span></th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="{tr_class}">
|
<tr class="{tr_class} mievr_in">
|
||||||
<td class="mievr">"""
|
<td class="mievr">"""
|
||||||
)
|
)
|
||||||
if can_edit_evals:
|
if can_edit_evals:
|
||||||
@ -832,7 +844,7 @@ def _evaluation_poids_html(evaluation: Evaluation, max_poids: float = 0.0) -> st
|
|||||||
+ "\n".join(
|
+ "\n".join(
|
||||||
[
|
[
|
||||||
f"""<div title="poids vers {ue.acronyme}: {poids:g}">
|
f"""<div title="poids vers {ue.acronyme}: {poids:g}">
|
||||||
<div style="--size:{math.sqrt(poids*(evaluation.coefficient or 0.)/max_poids*144)}px;
|
<div style="--size:{math.sqrt(poids*(evaluation.coefficient)/max_poids*144)}px;
|
||||||
{'background-color: ' + ue.color + ';' if ue.color else ''}
|
{'background-color: ' + ue.color + ';' if ue.color else ''}
|
||||||
"></div>
|
"></div>
|
||||||
</div>"""
|
</div>"""
|
||||||
|
@ -884,7 +884,7 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
|||||||
if evaluation.date_debut:
|
if evaluation.date_debut:
|
||||||
indication_date = evaluation.date_debut.date().isoformat()
|
indication_date = evaluation.date_debut.date().isoformat()
|
||||||
else:
|
else:
|
||||||
indication_date = scu.sanitize_filename(evaluation.description or "")[:12]
|
indication_date = scu.sanitize_filename(evaluation.description)[:12]
|
||||||
eval_name = f"{evaluation.moduleimpl.module.code}-{indication_date}"
|
eval_name = f"{evaluation.moduleimpl.module.code}-{indication_date}"
|
||||||
|
|
||||||
date_str = (
|
date_str = (
|
||||||
|
@ -1469,6 +1469,9 @@ span.eval_title {
|
|||||||
font-size: 14pt;
|
font-size: 14pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#evaluation-edit-blocked td, #evaluation-edit-coef td {
|
||||||
|
padding-top: 24px;
|
||||||
|
}
|
||||||
/* #saisie_notes span.eval_title {
|
/* #saisie_notes span.eval_title {
|
||||||
border-bottom: 1px solid rgb(100,100,100);
|
border-bottom: 1px solid rgb(100,100,100);
|
||||||
}
|
}
|
||||||
@ -2099,6 +2102,14 @@ th.moduleimpl_evaluations a:hover {
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr.mievr_in.evaluation_blocked th.moduleimpl_evaluation_moy span, tr.evaluation_blocked th.moduleimpl_evaluation_moy a {
|
||||||
|
font-weight: bold;
|
||||||
|
color: red;
|
||||||
|
background-color: yellow;
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
tr.mievr {
|
tr.mievr {
|
||||||
background-color: #eeeeee;
|
background-color: #eeeeee;
|
||||||
}
|
}
|
||||||
@ -2153,6 +2164,15 @@ tr.mievr.non_visible_inter th {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr.mievr_tit.evaluation_blocked td,tr.mievr_tit.evaluation_blocked th {
|
||||||
|
background-image: radial-gradient(#bd7777 1px, transparent 1px);
|
||||||
|
background-size: 10px 10px;
|
||||||
|
}
|
||||||
|
tr.mievr_in.evaluation_blocked td, tr.mievr_in.evaluation_blocked th {
|
||||||
|
background-color: rgb(195, 235, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
tr.mievr th {
|
tr.mievr th {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
@ -2163,6 +2183,7 @@ tr.mievr td.mievr {
|
|||||||
|
|
||||||
tr.mievr td.mievr_menu {
|
tr.mievr td.mievr_menu {
|
||||||
width: 110px;
|
width: 110px;
|
||||||
|
padding-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.mievr td.mievr_dur {
|
tr.mievr td.mievr_dur {
|
||||||
|
@ -457,7 +457,7 @@ class TableRecap(tb.Table):
|
|||||||
row_descr_eval.add_cell(
|
row_descr_eval.add_cell(
|
||||||
col_id,
|
col_id,
|
||||||
None,
|
None,
|
||||||
e.description or "",
|
e.description,
|
||||||
target=url_for(
|
target=url_for(
|
||||||
"notes.evaluation_listenotes",
|
"notes.evaluation_listenotes",
|
||||||
scodoc_dept=g.scodoc_dept,
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
@ -20,7 +20,7 @@ Assiduité lors de l'évaluation
|
|||||||
<a class="stdlink" href="{{
|
<a class="stdlink" href="{{
|
||||||
url_for('notes.evaluation_listenotes',
|
url_for('notes.evaluation_listenotes',
|
||||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation.id)
|
||||||
}}"><em>{{evaluation.description or ''}}</em></a>
|
}}"><em>{{evaluation.description}}</em></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a style="margin-left:32px;" href="{{request.url}}&fmt=xlsx">{{scu.ICON_XLS|safe}}</a>
|
<a style="margin-left:32px;" href="{{request.url}}&fmt=xlsx">{{scu.ICON_XLS|safe}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1642,7 +1642,7 @@ def evaluation_delete(evaluation_id):
|
|||||||
.first_or_404()
|
.first_or_404()
|
||||||
)
|
)
|
||||||
|
|
||||||
tit = f"""Suppression de l'évaluation {evaluation.description or ""} ({evaluation.descr_date()})"""
|
tit = f"""Suppression de l'évaluation {evaluation.description} ({evaluation.descr_date()})"""
|
||||||
etat = sco_evaluations.do_evaluation_etat(evaluation.id)
|
etat = sco_evaluations.do_evaluation_etat(evaluation.id)
|
||||||
H = [
|
H = [
|
||||||
f"""
|
f"""
|
||||||
|
83
migrations/versions/cddabc3f868a_evaluation_bloquee.py
Normal file
83
migrations/versions/cddabc3f868a_evaluation_bloquee.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
"""evaluation bloquee
|
||||||
|
|
||||||
|
Revision ID: cddabc3f868a
|
||||||
|
Revises: 2e4875004e12
|
||||||
|
Create Date: 2024-02-25 16:39:45.947342
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.orm import sessionmaker # added by ev
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "cddabc3f868a"
|
||||||
|
down_revision = "2e4875004e12"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
Session = sessionmaker()
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ces champs étaient nullables
|
||||||
|
# Added by ev: remove duplicates
|
||||||
|
bind = op.get_bind()
|
||||||
|
session = Session(bind=bind)
|
||||||
|
session.execute(
|
||||||
|
sa.text(
|
||||||
|
"""UPDATE notes_evaluation SET description='' WHERE description IS NULL;"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
session.execute(
|
||||||
|
sa.text("""UPDATE notes_evaluation SET note_max=20. WHERE note_max IS NULL;""")
|
||||||
|
)
|
||||||
|
session.execute(
|
||||||
|
sa.text(
|
||||||
|
"""UPDATE notes_evaluation SET coefficient=0. WHERE coefficient IS NULL;"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
#
|
||||||
|
with op.batch_alter_table("notes_evaluation", schema=None) as batch_op:
|
||||||
|
batch_op.add_column(
|
||||||
|
sa.Column("blocked_until", sa.DateTime(timezone=True), nullable=True)
|
||||||
|
)
|
||||||
|
batch_op.alter_column("description", existing_type=sa.TEXT(), nullable=False)
|
||||||
|
batch_op.alter_column(
|
||||||
|
"note_max", existing_type=sa.DOUBLE_PRECISION(precision=53), nullable=False
|
||||||
|
)
|
||||||
|
batch_op.alter_column(
|
||||||
|
"coefficient",
|
||||||
|
existing_type=sa.DOUBLE_PRECISION(precision=53),
|
||||||
|
nullable=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
with op.batch_alter_table("notes_formsemestre", schema=None) as batch_op:
|
||||||
|
batch_op.add_column(
|
||||||
|
sa.Column(
|
||||||
|
"mode_calcul_moyennes", sa.Integer(), server_default="0", nullable=False
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table("notes_formsemestre", schema=None) as batch_op:
|
||||||
|
batch_op.drop_column("mode_calcul_moyennes")
|
||||||
|
|
||||||
|
with op.batch_alter_table("notes_evaluation", schema=None) as batch_op:
|
||||||
|
batch_op.alter_column(
|
||||||
|
"coefficient",
|
||||||
|
existing_type=sa.DOUBLE_PRECISION(precision=53),
|
||||||
|
nullable=True,
|
||||||
|
)
|
||||||
|
batch_op.alter_column(
|
||||||
|
"note_max", existing_type=sa.DOUBLE_PRECISION(precision=53), nullable=True
|
||||||
|
)
|
||||||
|
batch_op.alter_column("description", existing_type=sa.TEXT(), nullable=True)
|
||||||
|
batch_op.drop_column("blocked_until")
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in New Issue
Block a user