From 857c3007a531a2d73429712779ebb3dcd0935a6d Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Wed, 8 Dec 2021 22:33:32 +0100 Subject: [PATCH] =?UTF-8?q?s=C3=A9pare=20mod=C3=A8les=20UE=20et=20Module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/but/bulletin_but.py | 2 +- app/models/__init__.py | 11 +- app/models/formations.py | 256 +--------------------------- app/models/formsemestre.py | 3 +- app/models/moduleimpls.py | 5 - app/models/modules.py | 185 ++++++++++++++++++++ app/models/ues.py | 84 +++++++++ app/scodoc/sco_abs.py | 24 +-- app/scodoc/sco_edit_apc.py | 2 +- app/scodoc/sco_edit_module.py | 2 +- app/scodoc/sco_edit_ue.py | 2 +- app/scodoc/sco_formsemestre_edit.py | 11 +- app/scodoc/sco_liste_notes.py | 8 +- app/static/js/bulletin-but.js | 4 +- app/views/notes.py | 2 +- app/views/pn_modules.py | 2 +- app/views/refcomp.py | 2 +- 17 files changed, 308 insertions(+), 297 deletions(-) create mode 100644 app/models/modules.py create mode 100644 app/models/ues.py diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py index 5cf7d9cd..52f72a26 100644 --- a/app/but/bulletin_but.py +++ b/app/but/bulletin_but.py @@ -126,7 +126,7 @@ class ResultatsSemestreBUT: "max": fmt_note(self.etud_moy_ue[ue.id].max()), "moy": fmt_note(self.etud_moy_ue[ue.id].mean()), }, - "bonus": 17.8, # None, # XXX TODO + "bonus": None, # XXX TODO "malus": None, # XXX TODO voir ce qui est ici "capitalise": None, # "AAAA-MM-JJ" TODO "ressources": self.etud_ue_mod_results(etud, ue, self.ressources), diff --git a/app/models/__init__.py b/app/models/__init__.py index 78af2bb8..119087dd 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -30,14 +30,9 @@ from app.models.etudiants import ( EtudAnnotation, ) from app.models.events import Scolog, ScolarNews -from app.models.formations import ( - Formation, - UniteEns, - Matiere, - Module, - ModuleUECoef, - NotesTag, -) +from app.models.formations import Formation, Matiere +from app.models.modules import Module, ModuleUECoef, NotesTag +from app.models.ues import UniteEns from app.models.formsemestre import ( FormSemestre, FormsemestreEtape, diff --git a/app/models/formations.py b/app/models/formations.py index 522af7a0..55de77f7 100644 --- a/app/models/formations.py +++ b/app/models/formations.py @@ -1,13 +1,10 @@ -"""ScoDoc8 models : Formations (hors BUT) +"""ScoDoc 9 models : Formations """ -from typing import Any from app import db -from app.models import APO_CODE_STR_LEN from app.models import SHORT_STR_LEN from app.scodoc import notesdb as ndb from app.scodoc import sco_utils as scu -from app.scodoc.sco_utils import ModuleType from app.scodoc import sco_codes_parcours from app.comp import df_cache @@ -91,82 +88,6 @@ class Formation(db.Model): df_cache.ModuleCoefsCache.delete_many(keys | {f"{self.id}"}) -class UniteEns(db.Model): - """Unité d'Enseignement (UE)""" - - __tablename__ = "notes_ue" - - id = db.Column(db.Integer, primary_key=True) - ue_id = db.synonym("id") - formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id")) - acronyme = db.Column(db.Text(), nullable=False) - numero = db.Column(db.Integer) # ordre de présentation - titre = db.Column(db.Text()) - # Le semestre_idx n'est pas un id mais le numéro du semestre: 1, 2, ... - # En ScoDoc7 et pour les formations classiques, il est NULL - # (le numéro du semestre étant alors déterminé par celui des modules de l'UE) - # Pour les formations APC, il est obligatoire (de 1 à 6 pour le BUT): - semestre_idx = db.Column(db.Integer, nullable=True, index=True) - # Type d'UE: 0 normal ("fondamentale"), 1 "sport", 2 "projet et stage (LP)", - # 4 "élective" - type = db.Column(db.Integer, default=0, server_default="0") - # Les UE sont "compatibles" (pour la capitalisation) ssi elles ont ^m code - # note: la fonction SQL notes_newid_ucod doit être créée à part - ue_code = db.Column( - db.String(SHORT_STR_LEN), - server_default=db.text("notes_newid_ucod()"), - nullable=False, - ) - ects = db.Column(db.Float) # nombre de credits ECTS - is_external = db.Column(db.Boolean(), default=False, server_default="false") - # id de l'element pedagogique Apogee correspondant: - code_apogee = db.Column(db.String(APO_CODE_STR_LEN)) - # coef UE, utilise seulement si l'option use_ue_coefs est activée: - coefficient = db.Column(db.Float) - - # relations - matieres = db.relationship("Matiere", lazy="dynamic", backref="ue") - modules = db.relationship("Module", lazy="dynamic", backref="ue") - - def __repr__(self): - return f"<{self.__class__.__name__}(id={self.id}, formation_id={self.formation_id}, acronyme='{self.acronyme}')>" - - def to_dict(self): - """as a dict, with the same conversions as in ScoDoc7""" - e = dict(self.__dict__) - e.pop("_sa_instance_state", None) - # ScoDoc7 output_formators - e["ue_id"] = self.id - e["numero"] = e["numero"] if e["numero"] else 0 - e["ects"] = e["ects"] if e["ects"] else 0.0 - e["coefficient"] = e["coefficient"] if e["coefficient"] else 0.0 - return e - - def is_locked(self): - """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 - - return sco_edit_ue.ue_is_locked(self.id) - - def guess_semestre_idx(self) -> None: - """Lorsqu'on prend une ancienne formation non APC, - les UE n'ont pas d'indication de semestre. - Cette méthode fixe le semestre en prenant celui du premier module, - ou à défaut le met à 1. - """ - if self.semestre_idx is None: - module = self.modules.first() - if module is None: - self.semestre_idx = 1 - else: - self.semestre_idx = module.semestre_id - db.session.add(self) - db.session.commit() - - class Matiere(db.Model): """Matières: regroupe les modules d'une UE La matière a peu d'utilité en dehors de la présentation des modules @@ -183,178 +104,3 @@ class Matiere(db.Model): numero = db.Column(db.Integer) # ordre de présentation modules = db.relationship("Module", lazy="dynamic", backref="matiere") - - -class Module(db.Model): - """Module""" - - __tablename__ = "notes_modules" - - id = db.Column(db.Integer, primary_key=True) - module_id = db.synonym("id") - titre = db.Column(db.Text()) - abbrev = db.Column(db.Text()) # nom court - # certains départements ont des codes infiniment longs: donc Text ! - code = db.Column(db.Text(), nullable=False) - heures_cours = db.Column(db.Float) - heures_td = db.Column(db.Float) - heures_tp = db.Column(db.Float) - coefficient = db.Column(db.Float) # coef PPN (sauf en APC) - ects = db.Column(db.Float) # Crédits ECTS - ue_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"), index=True) - formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id")) - matiere_id = db.Column(db.Integer, db.ForeignKey("notes_matieres.id")) - # pas un id mais le numéro du semestre: 1, 2, ... - semestre_id = db.Column(db.Integer, nullable=False, default=1, server_default="1") - numero = db.Column(db.Integer) # ordre de présentation - # id de l'element pedagogique Apogee correspondant: - code_apogee = db.Column(db.String(APO_CODE_STR_LEN)) - # Type: ModuleType: DEFAULT, MALUS, RESSOURCE, MODULE_SAE (enum) - module_type = db.Column(db.Integer) - # Relations: - modimpls = db.relationship("ModuleImpl", backref="module", lazy="dynamic") - ues_apc = db.relationship("UniteEns", secondary="module_ue_coef", viewonly=True) - tags = db.relationship( - "NotesTag", - secondary="notes_modules_tags", - lazy=True, - backref=db.backref("modules", lazy=True), - ) - - def __init__(self, **kwargs): - self.ue_coefs = [] - super(Module, self).__init__(**kwargs) - - def __repr__(self): - return ( - f"" - ) - - def to_dict(self): - e = dict(self.__dict__) - e.pop("_sa_instance_state", None) - # ScoDoc7 output_formators: (backward compat) - e["module_id"] = self.id - e["heures_cours"] = 0.0 if self.heures_cours is None else self.heures_cours - e["heures_td"] = 0.0 if self.heures_td is None else self.heures_td - e["heures_tp"] = 0.0 if self.heures_tp is None else self.heures_tp - e["numero"] = 0 if self.numero is None else self.numero - e["coefficient"] = 0.0 if self.coefficient is None else self.coefficient - e["module_type"] = 0 if self.module_type is None else self.module_type - return e - - def is_apc(self): - "True si module SAÉ ou Ressource" - return self.module_type and scu.ModuleType(self.module_type) in { - scu.ModuleType.RESSOURCE, - scu.ModuleType.SAE, - } - - def type_name(self): - return scu.MODULE_TYPE_NAMES[self.module_type] - - def set_ue_coef(self, ue, coef: float) -> None: - """Set coef module vers cette UE""" - self.update_ue_coef_dict({ue.id: coef}) - - def set_ue_coef_dict(self, ue_coef_dict: dict) -> None: - """set coefs vers les UE (remplace existants) - ue_coef_dict = { ue_id : coef } - Les coefs nuls (zéro) ne sont pas stockés: la relation est supprimée. - """ - ue_coefs = [] - for ue_id, coef in ue_coef_dict.items(): - ue = UniteEns.query.get(ue_id) - if coef == 0.0: - self.delete_ue_coef(ue) - else: - ue_coefs.append(ModuleUECoef(module=self, ue=ue, coef=coef)) - self.ue_coefs = ue_coefs - self.formation.invalidate_module_coefs() - - def update_ue_coef_dict(self, ue_coef_dict: dict): - """update coefs vers UE (ajoute aux existants)""" - current = self.get_ue_coef_dict() - current.update(ue_coef_dict) - self.set_ue_coef_dict(current) - - def get_ue_coef_dict(self): - """returns { ue_id : coef }""" - return {p.ue.id: p.coef for p in self.ue_coefs} - - def delete_ue_coef(self, ue): - """delete coef""" - ue_coef = ModuleUECoef.query.get((self.id, ue.id)) - if ue_coef: - db.session.delete(ue_coef) - self.formation.invalidate_module_coefs() - - def ue_coefs_descr(self): - """List of tuples [ (ue_acronyme, coef) ]""" - return [(c.ue.acronyme, c.coef) for c in self.ue_coefs] - - -class ModuleUECoef(db.Model): - """Coefficients des modules vers les UE (APC, BUT) - En mode APC, ces coefs remplacent le coefficient "PPN" du module. - """ - - __tablename__ = "module_ue_coef" - - module_id = db.Column( - db.Integer, - db.ForeignKey("notes_modules.id", ondelete="CASCADE"), - primary_key=True, - ) - ue_id = db.Column( - db.Integer, - db.ForeignKey("notes_ue.id", ondelete="CASCADE"), - primary_key=True, - ) - coef = db.Column( - db.Float, - nullable=False, - ) - module = db.relationship( - Module, - backref=db.backref( - "ue_coefs", - passive_deletes=True, - cascade="save-update, merge, delete, delete-orphan", - ), - ) - ue = db.relationship( - UniteEns, - backref=db.backref( - "module_ue_coefs", - passive_deletes=True, - cascade="save-update, merge, delete, delete-orphan", - ), - ) - - -class NotesTag(db.Model): - """Tag sur un module""" - - __tablename__ = "notes_tags" - __table_args__ = (db.UniqueConstraint("title", "dept_id"),) - - id = db.Column(db.Integer, primary_key=True) - tag_id = db.synonym("id") - - dept_id = db.Column(db.Integer, db.ForeignKey("departement.id"), index=True) - title = db.Column(db.Text(), nullable=False) - - -# Association tag <-> module -notes_modules_tags = db.Table( - "notes_modules_tags", - db.Column( - "tag_id", - db.Integer, - db.ForeignKey("notes_tags.id", ondelete="CASCADE"), - ), - db.Column( - "module_id", db.Integer, db.ForeignKey("notes_modules.id", ondelete="CASCADE") - ), -) diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py index f066110f..343e7689 100644 --- a/app/models/formsemestre.py +++ b/app/models/formsemestre.py @@ -16,7 +16,8 @@ from app.models import UniteEns import app.scodoc.notesdb as ndb import app.scodoc.sco_utils as scu from app.scodoc import sco_evaluation_db -from app.models.formations import UniteEns, Module +from app.models.ues import UniteEns +from app.models.modules import Module from app.models.moduleimpls import ModuleImpl from app.models.etudiants import Identite from app.scodoc import sco_codes_parcours diff --git a/app/models/moduleimpls.py b/app/models/moduleimpls.py index 38f95c57..05bd592a 100644 --- a/app/models/moduleimpls.py +++ b/app/models/moduleimpls.py @@ -2,19 +2,14 @@ """ScoDoc models: moduleimpls """ -from typing import Any import pandas as pd from app import db from app.comp import df_cache -from app.models import APO_CODE_STR_LEN -from app.models import SHORT_STR_LEN -from app.models import CODE_STR_LEN from app.models import UniteEns, Identite import app.scodoc.notesdb as ndb -from app.scodoc import sco_evaluation_db from app.scodoc import sco_utils as scu diff --git a/app/models/modules.py b/app/models/modules.py new file mode 100644 index 00000000..726dd5f2 --- /dev/null +++ b/app/models/modules.py @@ -0,0 +1,185 @@ +"""ScoDoc 9 models : Modules +""" +from typing import Any + +from app import db +from app.models import APO_CODE_STR_LEN +from app.scodoc import sco_utils as scu +from app.scodoc.sco_utils import ModuleType + + +class Module(db.Model): + """Module""" + + __tablename__ = "notes_modules" + + id = db.Column(db.Integer, primary_key=True) + module_id = db.synonym("id") + titre = db.Column(db.Text()) + abbrev = db.Column(db.Text()) # nom court + # certains départements ont des codes infiniment longs: donc Text ! + code = db.Column(db.Text(), nullable=False) + heures_cours = db.Column(db.Float) + heures_td = db.Column(db.Float) + heures_tp = db.Column(db.Float) + coefficient = db.Column(db.Float) # coef PPN (sauf en APC) + ects = db.Column(db.Float) # Crédits ECTS + ue_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"), index=True) + formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id")) + matiere_id = db.Column(db.Integer, db.ForeignKey("notes_matieres.id")) + # pas un id mais le numéro du semestre: 1, 2, ... + semestre_id = db.Column(db.Integer, nullable=False, default=1, server_default="1") + numero = db.Column(db.Integer) # ordre de présentation + # id de l'element pedagogique Apogee correspondant: + code_apogee = db.Column(db.String(APO_CODE_STR_LEN)) + # Type: ModuleType: DEFAULT, MALUS, RESSOURCE, MODULE_SAE (enum) + module_type = db.Column(db.Integer) + # Relations: + modimpls = db.relationship("ModuleImpl", backref="module", lazy="dynamic") + ues_apc = db.relationship("UniteEns", secondary="module_ue_coef", viewonly=True) + tags = db.relationship( + "NotesTag", + secondary="notes_modules_tags", + lazy=True, + backref=db.backref("modules", lazy=True), + ) + + def __init__(self, **kwargs): + self.ue_coefs = [] + super(Module, self).__init__(**kwargs) + + def __repr__(self): + return ( + f"" + ) + + def to_dict(self): + e = dict(self.__dict__) + e.pop("_sa_instance_state", None) + # ScoDoc7 output_formators: (backward compat) + e["module_id"] = self.id + e["heures_cours"] = 0.0 if self.heures_cours is None else self.heures_cours + e["heures_td"] = 0.0 if self.heures_td is None else self.heures_td + e["heures_tp"] = 0.0 if self.heures_tp is None else self.heures_tp + e["numero"] = 0 if self.numero is None else self.numero + e["coefficient"] = 0.0 if self.coefficient is None else self.coefficient + e["module_type"] = 0 if self.module_type is None else self.module_type + return e + + def is_apc(self): + "True si module SAÉ ou Ressource" + return self.module_type and scu.ModuleType(self.module_type) in { + scu.ModuleType.RESSOURCE, + scu.ModuleType.SAE, + } + + def type_name(self): + return scu.MODULE_TYPE_NAMES[self.module_type] + + def set_ue_coef(self, ue, coef: float) -> None: + """Set coef module vers cette UE""" + self.update_ue_coef_dict({ue.id: coef}) + + def set_ue_coef_dict(self, ue_coef_dict: dict) -> None: + """set coefs vers les UE (remplace existants) + ue_coef_dict = { ue_id : coef } + Les coefs nuls (zéro) ne sont pas stockés: la relation est supprimée. + """ + ue_coefs = [] + for ue_id, coef in ue_coef_dict.items(): + ue = UniteEns.query.get(ue_id) + if coef == 0.0: + self.delete_ue_coef(ue) + else: + ue_coefs.append(ModuleUECoef(module=self, ue=ue, coef=coef)) + self.ue_coefs = ue_coefs + self.formation.invalidate_module_coefs() + + def update_ue_coef_dict(self, ue_coef_dict: dict): + """update coefs vers UE (ajoute aux existants)""" + current = self.get_ue_coef_dict() + current.update(ue_coef_dict) + self.set_ue_coef_dict(current) + + def get_ue_coef_dict(self): + """returns { ue_id : coef }""" + return {p.ue.id: p.coef for p in self.ue_coefs} + + def delete_ue_coef(self, ue): + """delete coef""" + ue_coef = ModuleUECoef.query.get((self.id, ue.id)) + if ue_coef: + db.session.delete(ue_coef) + self.formation.invalidate_module_coefs() + + def ue_coefs_descr(self): + """List of tuples [ (ue_acronyme, coef) ]""" + return [(c.ue.acronyme, c.coef) for c in self.ue_coefs] + + +class ModuleUECoef(db.Model): + """Coefficients des modules vers les UE (APC, BUT) + En mode APC, ces coefs remplacent le coefficient "PPN" du module. + """ + + __tablename__ = "module_ue_coef" + + module_id = db.Column( + db.Integer, + db.ForeignKey("notes_modules.id", ondelete="CASCADE"), + primary_key=True, + ) + ue_id = db.Column( + db.Integer, + db.ForeignKey("notes_ue.id", ondelete="CASCADE"), + primary_key=True, + ) + coef = db.Column( + db.Float, + nullable=False, + ) + module = db.relationship( + Module, + backref=db.backref( + "ue_coefs", + passive_deletes=True, + cascade="save-update, merge, delete, delete-orphan", + ), + ) + ue = db.relationship( + "UniteEns", + backref=db.backref( + "module_ue_coefs", + passive_deletes=True, + cascade="save-update, merge, delete, delete-orphan", + ), + ) + + +class NotesTag(db.Model): + """Tag sur un module""" + + __tablename__ = "notes_tags" + __table_args__ = (db.UniqueConstraint("title", "dept_id"),) + + id = db.Column(db.Integer, primary_key=True) + tag_id = db.synonym("id") + + dept_id = db.Column(db.Integer, db.ForeignKey("departement.id"), index=True) + title = db.Column(db.Text(), nullable=False) + + +# Association tag <-> module +notes_modules_tags = db.Table( + "notes_modules_tags", + db.Column( + "tag_id", + db.Integer, + db.ForeignKey("notes_tags.id", ondelete="CASCADE"), + ), + db.Column( + "module_id", db.Integer, db.ForeignKey("notes_modules.id", ondelete="CASCADE") + ), +) + +from app.models.ues import UniteEns diff --git a/app/models/ues.py b/app/models/ues.py new file mode 100644 index 00000000..e3cd05a0 --- /dev/null +++ b/app/models/ues.py @@ -0,0 +1,84 @@ +"""ScoDoc 9 models : Unités d'Enseignement (UE) +""" + +from app import db +from app.models import APO_CODE_STR_LEN +from app.models import SHORT_STR_LEN +from app.scodoc import notesdb as ndb +from app.scodoc import sco_utils as scu + + +class UniteEns(db.Model): + """Unité d'Enseignement (UE)""" + + __tablename__ = "notes_ue" + + id = db.Column(db.Integer, primary_key=True) + ue_id = db.synonym("id") + formation_id = db.Column(db.Integer, db.ForeignKey("notes_formations.id")) + acronyme = db.Column(db.Text(), nullable=False) + numero = db.Column(db.Integer) # ordre de présentation + titre = db.Column(db.Text()) + # Le semestre_idx n'est pas un id mais le numéro du semestre: 1, 2, ... + # En ScoDoc7 et pour les formations classiques, il est NULL + # (le numéro du semestre étant alors déterminé par celui des modules de l'UE) + # Pour les formations APC, il est obligatoire (de 1 à 6 pour le BUT): + semestre_idx = db.Column(db.Integer, nullable=True, index=True) + # Type d'UE: 0 normal ("fondamentale"), 1 "sport", 2 "projet et stage (LP)", + # 4 "élective" + type = db.Column(db.Integer, default=0, server_default="0") + # Les UE sont "compatibles" (pour la capitalisation) ssi elles ont ^m code + # note: la fonction SQL notes_newid_ucod doit être créée à part + ue_code = db.Column( + db.String(SHORT_STR_LEN), + server_default=db.text("notes_newid_ucod()"), + nullable=False, + ) + ects = db.Column(db.Float) # nombre de credits ECTS + is_external = db.Column(db.Boolean(), default=False, server_default="false") + # id de l'element pedagogique Apogee correspondant: + code_apogee = db.Column(db.String(APO_CODE_STR_LEN)) + # coef UE, utilise seulement si l'option use_ue_coefs est activée: + coefficient = db.Column(db.Float) + + # relations + matieres = db.relationship("Matiere", lazy="dynamic", backref="ue") + modules = db.relationship("Module", lazy="dynamic", backref="ue") + + def __repr__(self): + return f"<{self.__class__.__name__}(id={self.id}, formation_id={self.formation_id}, acronyme='{self.acronyme}')>" + + def to_dict(self): + """as a dict, with the same conversions as in ScoDoc7""" + e = dict(self.__dict__) + e.pop("_sa_instance_state", None) + # ScoDoc7 output_formators + e["ue_id"] = self.id + e["numero"] = e["numero"] if e["numero"] else 0 + e["ects"] = e["ects"] if e["ects"] else 0.0 + e["coefficient"] = e["coefficient"] if e["coefficient"] else 0.0 + return e + + def is_locked(self): + """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 + + return sco_edit_ue.ue_is_locked(self.id) + + def guess_semestre_idx(self) -> None: + """Lorsqu'on prend une ancienne formation non APC, + les UE n'ont pas d'indication de semestre. + Cette méthode fixe le semestre en prenant celui du premier module, + ou à défaut le met à 1. + """ + if self.semestre_idx is None: + module = self.modules.first() + if module is None: + self.semestre_idx = 1 + else: + self.semestre_idx = module.semestre_id + db.session.add(self) + db.session.commit() diff --git a/app/scodoc/sco_abs.py b/app/scodoc/sco_abs.py index 28bfa988..4ec994ab 100644 --- a/app/scodoc/sco_abs.py +++ b/app/scodoc/sco_abs.py @@ -546,21 +546,21 @@ def list_abs_non_just(etudid, datedebut): cnx = ndb.GetDBConnexion() cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( - """SELECT ETUDID, JOUR, MATIN FROM ABSENCES A + """SELECT ETUDID, JOUR, MATIN FROM ABSENCES A WHERE A.ETUDID = %(etudid)s -AND A.estabs +AND A.estabs AND A.jour >= %(datedebut)s -EXCEPT SELECT ETUDID, JOUR, MATIN FROM ABSENCES B -WHERE B.estjust +EXCEPT SELECT ETUDID, JOUR, MATIN FROM ABSENCES B +WHERE B.estjust AND B.ETUDID = %(etudid)s ORDER BY JOUR """, vars(), ) - A = cursor.dictfetchall() - for a in A: + abs_list = cursor.dictfetchall() + for a in abs_list: a["description"] = _get_abs_description(a, cursor=cursor) - return A + return abs_list def list_abs_just(etudid, datedebut): @@ -570,7 +570,7 @@ def list_abs_just(etudid, datedebut): cursor.execute( """SELECT DISTINCT A.ETUDID, A.JOUR, A.MATIN FROM ABSENCES A, ABSENCES B WHERE A.ETUDID = %(etudid)s -AND A.ETUDID = B.ETUDID +AND A.ETUDID = B.ETUDID AND A.JOUR = B.JOUR AND A.MATIN = B.MATIN AND A.JOUR >= %(datedebut)s AND A.ESTABS AND (A.ESTJUST OR B.ESTJUST) ORDER BY A.JOUR @@ -638,8 +638,12 @@ def add_absence( cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( """ - INSERT into absences (etudid,jour,estabs,estjust,matin,description, moduleimpl_id) - VALUES (%(etudid)s, %(jour)s, true, %(estjust)s, %(matin)s, %(description)s, %(moduleimpl_id)s ) + INSERT into absences + (etudid, jour, estabs, estjust, matin, description, moduleimpl_id) + VALUES + (%(etudid)s, %(jour)s, true, %(estjust)s, %(matin)s, + %(description)s, %(moduleimpl_id)s + ) """, vars(), ) diff --git a/app/scodoc/sco_edit_apc.py b/app/scodoc/sco_edit_apc.py index 6215903b..200d26d8 100644 --- a/app/scodoc/sco_edit_apc.py +++ b/app/scodoc/sco_edit_apc.py @@ -28,7 +28,7 @@ import flask from flask import url_for, render_template from flask import g, request from flask_login import current_user -from app.models.formations import Formation, UniteEns, Matiere, Module +from app.models import Formation, UniteEns, Matiere, Module import app.scodoc.notesdb as ndb import app.scodoc.sco_utils as scu diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py index 7bf09fce..73336d39 100644 --- a/app/scodoc/sco_edit_module.py +++ b/app/scodoc/sco_edit_module.py @@ -32,7 +32,7 @@ import flask from flask import url_for, render_template from flask import g, request from flask_login import current_user -from app.models.formations import Matiere, UniteEns +from app.models import Matiere, UniteEns import app.scodoc.notesdb as ndb import app.scodoc.sco_utils as scu diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py index 9b48fad5..ba6781c6 100644 --- a/app/scodoc/sco_edit_ue.py +++ b/app/scodoc/sco_edit_ue.py @@ -33,7 +33,7 @@ from flask import url_for, render_template from flask import g, request from flask_login import current_user -from app.models.formations import Formation, UniteEns +from app.models import Formation, UniteEns import app.scodoc.notesdb as ndb import app.scodoc.sco_utils as scu from app.scodoc.sco_utils import ModuleType diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index 364f430f..b63e5678 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -1106,7 +1106,7 @@ def formsemestre_associate_new_version( "etat": "1", }, ) - of = [] + H = [] for s in othersems: if ( s["formsemestre_id"] == formsemestre_id @@ -1119,9 +1119,10 @@ def formsemestre_associate_new_version( disabled = 'disabled="1"' else: disabled = "" - of.append( - '
%s
' - % (s["formsemestre_id"], checked, disabled, s["titremois"]) + H.append( + f"""
{s['titremois']}
""" ) return scu.confirm_dialog( @@ -1130,7 +1131,7 @@ def formsemestre_associate_new_version(

Veillez à ne pas abuser de cette possibilité, car créer trop de versions de formations va vous compliquer la gestion (à vous de garder trace des différences et à ne pas vous tromper par la suite...).

Si vous voulez associer aussi d'autres semestres à la nouvelle version, cochez-les:

""" - + "".join(of) + + "".join(H) + "
", OK="Associer ces semestres à une nouvelle version", dest_url="", diff --git a/app/scodoc/sco_liste_notes.py b/app/scodoc/sco_liste_notes.py index a7c85ef5..dd465fc0 100644 --- a/app/scodoc/sco_liste_notes.py +++ b/app/scodoc/sco_liste_notes.py @@ -826,7 +826,7 @@ def _add_apc_columns( col_id = f"moy_ue_{ue.id}" titles[col_id] = ue.acronyme columns_ids.append(col_id) - row_coefs[f"moy_ue_{ue.id}"] = [uc for uc in ue_coefs if uc.ue_id == ue.id][ - 0 - ].coef - row_coefs[f"_moy_ue_{ue.id}_td_attrs"] = ' class="coef_mod_ue" ' + coefs = [uc for uc in ue_coefs if uc.ue_id == ue.id] + if coefs: + row_coefs[f"moy_ue_{ue.id}"] = coefs[0].coef + row_coefs[f"_moy_ue_{ue.id}_td_attrs"] = ' class="coef_mod_ue" ' diff --git a/app/static/js/bulletin-but.js b/app/static/js/bulletin-but.js index da73ea41..159a8ffe 100644 --- a/app/static/js/bulletin-but.js +++ b/app/static/js/bulletin-but.js @@ -115,7 +115,7 @@ function showSynthese(data) { ${(dataUE.competence) ? dataUE.competence + " - " : ""}${ue}
-
Moyenn : ${dataUE.moyenne?.value || "-"}
+
Moyenne : ${dataUE.moyenne?.value || "-"}
Bonus : ${dataUE.bonus || 0} - Malus : ${dataUE.malus || 0} @@ -125,7 +125,7 @@ function showSynthese(data) {
-
Abs inj.
${dataUE.absences?.injustifie || 0}
+
Abs N.J.
${dataUE.absences?.injustifie || 0}
Total
${dataUE.absences?.total || 0}
diff --git a/app/views/notes.py b/app/views/notes.py index add4ff32..181aff41 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -381,7 +381,7 @@ def ue_table(formation_id=None, semestre_idx=1, msg=""): @scodoc7func def ue_set_internal(ue_id): """""" - ue = models.formations.UniteEns.query.get(ue_id) + ue = models.UniteEns.query.get(ue_id) if not ue: raise ScoValueError("invalid ue_id") ue.is_external = False diff --git a/app/views/pn_modules.py b/app/views/pn_modules.py index 849e13e7..aa7374a9 100644 --- a/app/views/pn_modules.py +++ b/app/views/pn_modules.py @@ -56,7 +56,7 @@ from app.scodoc import notesdb as ndb from app.scodoc import sco_formations from app import log -from app.models.formations import Formation, UniteEns, Module +from app.models import Formation, UniteEns, Module from app.scodoc.sco_exceptions import ( ScoValueError, ScoLockedFormError, diff --git a/app/views/refcomp.py b/app/views/refcomp.py index 3eb7f142..a144b390 100644 --- a/app/views/refcomp.py +++ b/app/views/refcomp.py @@ -18,7 +18,7 @@ from app import db from app import models from app.decorators import scodoc, permission_required -from app.models.formations import Formation +from app.models import Formation from app.models.but_refcomp import ApcReferentielCompetences from app.but.import_refcomp import orebut_import_refcomp from app.but.forms.refcomp_forms import FormationRefCompForm, RefCompLoadForm