From 44db5028fdf1bd0577a14dd1511cb2a99b14935c Mon Sep 17 00:00:00 2001 From: Jean-Marie Place Date: Thu, 30 Sep 2021 16:52:23 +0200 Subject: [PATCH] resize select control for placement --- README.md | 9 ++---- app/__init__.py | 10 ++----- app/auth/models.py | 14 ++++------ app/scodoc/bonus_sport.py | 17 ------------ app/scodoc/sco_debouche.py | 34 ++++++++--------------- app/scodoc/sco_excel.py | 12 ++++---- app/scodoc/sco_import_etuds.py | 28 ++++++++++--------- app/scodoc/sco_import_users.py | 6 ++-- app/scodoc/sco_liste_notes.py | 4 +-- app/scodoc/sco_parcours_dut.py | 2 +- app/scodoc/sco_placement.py | 3 +- app/templates/scodoc/forms/placement.html | 4 +-- app/views/notes.py | 4 --- app/views/scolar.py | 4 +-- app/views/users.py | 13 ++++----- sco_version.py | 2 +- scodoc.py | 1 + tests/unit/test_sco_basic.py | 17 ------------ tools/import_scodoc7_user_db.py | 2 +- 19 files changed, 61 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index 014e6869f..753fc3dc9 100644 --- a/README.md +++ b/README.md @@ -106,15 +106,13 @@ Ou avec couverture (`pip install pytest-cov`) #### Utilisation des tests unitaires pour initialiser la base de dev On peut aussi utiliser les tests unitaires pour mettre la base -de données de développement dans un état connu, par exemple pour éviter de -recréer à la main étudianst et semestres quand on développe. +de données de développement dans un état connu, par exemple pour éviter de recréer à la main étudianst et semestres quand on développe. Il suffit de positionner une variable d'environnement indiquant la BD utilisée par les tests: export SCODOC_TEST_DATABASE_URI=postgresql:///SCODOC_DEV -(si elle n'existe pas, voir plus loin pour la créer) puis de les lancer -normalement, par exemple: +puis de les lancer normalement, par exemple: pytest tests/unit/test_sco_basic.py @@ -135,8 +133,7 @@ On utilise SQLAlchemy avec Alembic et Flask-Migrate. Ne pas oublier de commiter les migrations (`git add migrations` ...). -Mémo pour développeurs: séquence re-création d'une base (vérifiez votre `.env` -ou variables d'environnement pour interroger la bonne base !). +Mémo pour développeurs: séquence re-création d'une base: dropdb SCODOC_DEV tools/create_database.sh SCODOC_DEV # créé base SQL diff --git a/app/__init__.py b/app/__init__.py index 25ea4f6b3..a3f048391 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -259,19 +259,15 @@ def create_app(config_class=DevConfig): ) # ---- INITIALISATION SPECIFIQUES A SCODOC from app.scodoc import sco_bulletins_generator - + from app.scodoc.sco_bulletins_example import BulletinGeneratorExample from app.scodoc.sco_bulletins_legacy import BulletinGeneratorLegacy from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard from app.scodoc.sco_bulletins_ucac import BulletinGeneratorUCAC - # l'ordre est important, le premeir sera le "défaut" pour les nouveaux départements. - sco_bulletins_generator.register_bulletin_class(BulletinGeneratorStandard) + sco_bulletins_generator.register_bulletin_class(BulletinGeneratorExample) sco_bulletins_generator.register_bulletin_class(BulletinGeneratorLegacy) + sco_bulletins_generator.register_bulletin_class(BulletinGeneratorStandard) sco_bulletins_generator.register_bulletin_class(BulletinGeneratorUCAC) - if app.testing or app.debug: - from app.scodoc.sco_bulletins_example import BulletinGeneratorExample - - sco_bulletins_generator.register_bulletin_class(BulletinGeneratorExample) return app diff --git a/app/auth/models.py b/app/auth/models.py index ed20d5eeb..d71ecf3f7 100644 --- a/app/auth/models.py +++ b/app/auth/models.py @@ -177,9 +177,8 @@ class User(UserMixin, db.Model): if "roles_string" in data: self.user_roles = [] for r_d in data["roles_string"].split(","): - if r_d: - role, dept = UserRole.role_dept_from_string(r_d) - self.add_role(role, dept) + role, dept = UserRole.role_dept_from_string(r_d) + self.add_role(role, dept) def get_token(self, expires_in=3600): now = datetime.utcnow() @@ -330,7 +329,7 @@ class Role(db.Model): """Roles for ScoDoc""" id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(64), unique=True) # TODO: , nullable=False)) + name = db.Column(db.String(64), unique=True) default = db.Column(db.Boolean, default=False, index=True) permissions = db.Column(db.BigInteger) # 64 bits users = db.relationship("User", secondary="user_role", viewonly=True) @@ -389,7 +388,7 @@ class UserRole(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("user.id")) role_id = db.Column(db.Integer, db.ForeignKey("role.id")) - dept = db.Column(db.String(64)) # dept acronym ou NULL + dept = db.Column(db.String(64)) # dept acronym user = db.relationship( User, backref=db.backref("user_roles", cascade="all, delete-orphan") ) @@ -408,9 +407,6 @@ class UserRole(db.Model): """ fields = role_dept.split("_", 1) # maxsplit=1, le dept peut contenir un "_" if len(fields) != 2: - current_app.logger.warning( - f"role_dept_from_string: Invalid role_dept '{role_dept}'" - ) raise ScoValueError("Invalid role_dept") role_name, dept = fields if dept == "": @@ -422,7 +418,7 @@ class UserRole(db.Model): def get_super_admin(): - """L'utilisateur admin (ou le premier, s'il y en a plusieurs). + """L'utilisateur admin (où le premier, s'il y en a plusieurs). Utilisé par les tests unitaires et le script de migration. """ admin_role = Role.query.filter_by(name="SuperAdmin").first() diff --git a/app/scodoc/bonus_sport.py b/app/scodoc/bonus_sport.py index 51762b4ce..1dcfaa45c 100644 --- a/app/scodoc/bonus_sport.py +++ b/app/scodoc/bonus_sport.py @@ -167,23 +167,6 @@ def bonus_iutlh(notes_sport, coefs, infos=None): return bonus -def bonus_nantes(notes_sport, coefs, infos=None): - """IUT de Nantes (Septembre 2018) - Nous avons différents types de bonification - bonfication Sport / Culture / engagement citoyen - Nous ajoutons sur le bulletin une bonification de 0,2 pour chaque item - la bonification totale ne doit pas excéder les 0,5 point. - Sur le bulletin nous ne mettons pas une note sur 20 mais directement les bonifications. - - Dans ScoDoc: on a déclaré une UE "sport&culture" dans laquelle on aura des modules - pour chaque activité (Sport, Associations, ...) - avec à chaque fois une note (ScoDoc l'affichera comme une note sur 20, mais en fait ce sera la - valeur de la bonification: entrer 0,1/20 signifiera un bonus de 0,1 point la moyenne générale) - """ - bonus = min(0.5, sum([x for x in notes_sport])) # plafonnement à 0.5 points - return bonus - - # Bonus sport IUT Tours def bonus_tours(notes_sport, coefs, infos=None): """Calcul bonus sport & culture IUT Tours sur moyenne generale diff --git a/app/scodoc/sco_debouche.py b/app/scodoc/sco_debouche.py index 4c0b8916a..b32b39dee 100644 --- a/app/scodoc/sco_debouche.py +++ b/app/scodoc/sco_debouche.py @@ -48,19 +48,9 @@ import sco_version def report_debouche_date(start_year=None, format="html"): - """Rapport (table) pour les débouchés des étudiants sortis - à partir de l'année indiquée. - """ + """Rapport (table) pour les débouchés des étudiants sortis à partir de l'année indiquée.""" if not start_year: - return report_debouche_ask_date("Année de début de la recherche") - else: - try: - start_year = int(start_year) - except ValueError: - return report_debouche_ask_date( - "Année invalide. Année de début de la recherche" - ) - + return report_debouche_ask_date() if format == "xls": keep_numeric = True # pas de conversion des notes en strings else: @@ -106,9 +96,8 @@ def get_etudids_with_debouche(start_year): FROM notes_formsemestre_inscription i, notes_formsemestre s, itemsuivi it WHERE i.etudid = it.etudid AND i.formsemestre_id = s.id AND s.date_fin >= %(start_date)s - AND s.dept_id = %(dept_id)s """, - {"start_date": start_date, "dept_id": g.scodoc_dept_id}, + {"start_date": start_date}, ) return [x["etudid"] for x in r] @@ -204,16 +193,15 @@ def table_debouche_etudids(etudids, keep_numeric=True): return tab -def report_debouche_ask_date(msg: str) -> str: +def report_debouche_ask_date(): """Formulaire demande date départ""" - return f"""{html_sco_header.sco_header()} -

Table des débouchés des étudiants

-
- {msg} - -
- {html_sco_header.sco_footer()} - """ + return ( + html_sco_header.sco_header() + + """
+ Date de départ de la recherche: +
""" + + html_sco_header.sco_footer() + ) # ---------------------------------------------------------------------------- diff --git a/app/scodoc/sco_excel.py b/app/scodoc/sco_excel.py index 6904062cf..e8c02fe94 100644 --- a/app/scodoc/sco_excel.py +++ b/app/scodoc/sco_excel.py @@ -568,9 +568,10 @@ def excel_bytes_to_list(bytes_content): return _excel_to_list(filelike) except: raise ScoValueError( - """Le fichier xlsx attendu n'est pas lisible ! - Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ..) """ + scolars_import_excel_file: un contenu xlsx semble corrompu! + peut-être avez vous fourni un fichier au mauvais format (txt, xls, ..) + """ ) @@ -579,9 +580,10 @@ def excel_file_to_list(filename): return _excel_to_list(filename) except: raise ScoValueError( - """Le fichier xlsx attendu n'est pas lisible ! - Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...) - """ + """scolars_import_excel_file: un contenu xlsx + semble corrompu ! + Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...) + """ ) diff --git a/app/scodoc/sco_import_etuds.py b/app/scodoc/sco_import_etuds.py index 1107b11fa..1c366268a 100644 --- a/app/scodoc/sco_import_etuds.py +++ b/app/scodoc/sco_import_etuds.py @@ -25,16 +25,16 @@ # ############################################################################## -""" Importation des étudiants à partir de fichiers CSV +""" Importation des etudiants à partir de fichiers CSV """ import collections -import io import os import re import time from datetime import date +import flask from flask import g, url_for import app.scodoc.sco_utils as scu @@ -252,7 +252,7 @@ def students_import_excel( def scolars_import_excel_file( - datafile: io.BytesIO, + datafile, formsemestre_id=None, check_homonyms=True, require_ine=False, @@ -414,14 +414,16 @@ def scolars_import_excel_file( if NbHomonyms: NbImportedHomonyms += 1 # Insert in DB tables - formsemestre_id_etud = _import_one_student( - cnx, - formsemestre_id, - values, - GroupIdInferers, - annee_courante, - created_etudids, - linenum, + formsemestre_to_invalidate.add( + _import_one_student( + cnx, + formsemestre_id, + values, + GroupIdInferers, + annee_courante, + created_etudids, + linenum, + ) ) # Verification proportion d'homonymes: si > 10%, abandonne @@ -520,7 +522,7 @@ def _import_one_student( annee_courante, created_etudids, linenum, -) -> int: +): """ Import d'un étudiant et inscription dans le semestre. Return: id du semestre dans lequel il a été inscrit. @@ -564,7 +566,7 @@ def _import_one_student( ) do_formsemestre_inscription_with_modules( - int(args["formsemestre_id"]), + args["formsemestre_id"], etudid, group_ids, etat="I", diff --git a/app/scodoc/sco_import_users.py b/app/scodoc/sco_import_users.py index 89ac9989a..68f5ecd3c 100644 --- a/app/scodoc/sco_import_users.py +++ b/app/scodoc/sco_import_users.py @@ -231,10 +231,8 @@ def import_users(users): roles_list = [] for role in u["roles"].split(","): try: - role = role.strip() - if role: - _, _ = UserRole.role_dept_from_string(role) - roles_list.append(role) + _, _ = UserRole.role_dept_from_string(role.strip()) + roles_list.append(role.strip()) except ScoValueError as value_error: user_ok = False append_msg("role %s : %s" % (role, value_error)) diff --git a/app/scodoc/sco_liste_notes.py b/app/scodoc/sco_liste_notes.py index c2ac6691e..672a8754f 100644 --- a/app/scodoc/sco_liste_notes.py +++ b/app/scodoc/sco_liste_notes.py @@ -61,7 +61,7 @@ def do_evaluation_listenotes(): Affichage des notes d'une évaluation args: evaluation_id ou moduleimpl_id - (si moduleimpl_id, affiche toutes les évaluations du module) + (si moduleimpl_id, affiche toutes les évaluatons du module) """ mode = None vals = scu.get_request_args() @@ -69,7 +69,7 @@ def do_evaluation_listenotes(): evaluation_id = int(vals["evaluation_id"]) mode = "eval" evals = sco_evaluations.do_evaluation_list({"evaluation_id": evaluation_id}) - if "moduleimpl_id" in vals and vals["moduleimpl_id"]: + if "moduleimpl_id" in vals: moduleimpl_id = int(vals["moduleimpl_id"]) mode = "module" evals = sco_evaluations.do_evaluation_list({"moduleimpl_id": moduleimpl_id}) diff --git a/app/scodoc/sco_parcours_dut.py b/app/scodoc/sco_parcours_dut.py index cb10bf4b5..be4f983f3 100644 --- a/app/scodoc/sco_parcours_dut.py +++ b/app/scodoc/sco_parcours_dut.py @@ -916,7 +916,7 @@ def formsemestre_validate_ues(formsemestre_id, etudid, code_etat_sem, assiduite) and ue_status["moy"] >= nt.parcours.NOTES_BARRE_VALID_UE ): code_ue = ADM - elif not isinstance(ue_status["moy"], float): + elif isinstance(ue_status["moy"], float): # aucune note (pas de moyenne) dans l'UE: ne la valide pas code_ue = None elif valid_semestre: diff --git a/app/scodoc/sco_placement.py b/app/scodoc/sco_placement.py index ac39c2bba..c2ef9d937 100644 --- a/app/scodoc/sco_placement.py +++ b/app/scodoc/sco_placement.py @@ -88,10 +88,9 @@ def _get_group_info(evaluation_id): groups_tree[partition][group_name] = group_id if partition != TOUS: has_groups = True - nb_groups = len(groups_tree) else: has_groups = False - nb_groups = 1 + nb_groups = sum([len(groups_tree[p]) for p in groups_tree]) return groups_tree, has_groups, nb_groups diff --git a/app/templates/scodoc/forms/placement.html b/app/templates/scodoc/forms/placement.html index 5d2c3c205..7631b743c 100644 --- a/app/templates/scodoc/forms/placement.html +++ b/app/templates/scodoc/forms/placement.html @@ -3,7 +3,7 @@ {% macro render_field(field) %} {{ field.label }} - {{ field()|safe }} + {{ field(**kwargs)|safe }} {% if field.errors %}