From fdc01a5c3b9377e17facfe610a30710d1cd65f2d Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet <emmanuel.viennet@gmail.com> Date: Sun, 20 Oct 2024 11:02:08 +0200 Subject: [PATCH] =?UTF-8?q?sco=5Fplacement:=20feuilles=20placement=20?= =?UTF-8?q?=C3=A9tudiants=20=C3=A9valuation:=20modernisation=20code.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/forms/multiselect.py | 8 +- app/scodoc/sco_placement.py | 129 ++++++++++-------------- app/templates/scodoc/forms/placement.j2 | 4 + sco_version.py | 2 +- 4 files changed, 63 insertions(+), 80 deletions(-) diff --git a/app/forms/multiselect.py b/app/forms/multiselect.py index 77b13626..820718f9 100644 --- a/app/forms/multiselect.py +++ b/app/forms/multiselect.py @@ -26,7 +26,8 @@ class MultiSelect: HTML : group_ids="val1"&group_ids="val2"... JS : ["val1","val2", ...] - **kwargs: Arguments supplémentaires (appliqué au multiselect en HTML <multi-select key="value" ...>) + **kwargs: Arguments supplémentaires (appliqués au multiselect en + HTML <multi-select key="value" ...>) """ def __init__( @@ -61,7 +62,8 @@ class MultiSelect: for value in values: selected = "selected" if value.get("selected", False) else "" single = "single" if value.get("single", False) else "" - opt = f"<option value='{value.get('value')}' {selected} {single} >{value.get('label')}</option>" + opt = f"""<option value='{value.get('value')}' {selected} {single} >{ + value.get('label')}</option>""" optgroup += opt optgroup += "</optgroup>" opts.append(optgroup) @@ -70,7 +72,7 @@ class MultiSelect: js: str = "{" + self.js + "}" export: str = "{" + self.export + "}" return f""" - <multi-select + <multi-select label="{self.label}" id="{self.html_id}" name="{self.name}" diff --git a/app/scodoc/sco_placement.py b/app/scodoc/sco_placement.py index 23eca4ae..3a4ac157 100644 --- a/app/scodoc/sco_placement.py +++ b/app/scodoc/sco_placement.py @@ -48,23 +48,16 @@ from wtforms import ( HiddenField, SelectMultipleField, ) -from app.models import Evaluation, Module, ModuleImpl +from app.models import Evaluation, Identite, ModuleImpl import app.scodoc.sco_utils as scu -import app.scodoc.notesdb as ndb from app.scodoc import sco_preferences from app.scodoc import sco_evaluations from app.scodoc import sco_excel from app.scodoc.sco_excel import ScoExcelBook, COLORS -from app.scodoc import sco_formsemestre from app.scodoc import sco_groups -from app.scodoc import sco_moduleimpl from app.scodoc.gen_tables import GenTable -from app.scodoc import sco_etud import sco_version -_ = lambda x: x # sans babel -_l = _ - COORD = "Coordonnées" SEQ = "Continue" @@ -83,11 +76,9 @@ def _get_group_info(evaluation_id): if partition not in groups_tree: groups_tree[partition] = {} groups_tree[partition][group_name] = group_id - if partition != TOUS: - has_groups = True - else: - has_groups = False - nb_groups = sum([len(groups_tree[p]) for p in groups_tree]) + has_groups = partition != TOUS + + nb_groups = sum(len(pg) for pg in groups_tree.values()) return groups_tree, has_groups, nb_groups @@ -102,9 +93,9 @@ class PlacementForm(FlaskForm): wtforms.validators.DataRequired("indiquez le format du fichier attendu"), ], ) - surveillants = StringField("Surveillants", validators=[]) - batiment = StringField("Batiment") - salle = StringField("Salle") + surveillants = StringField("Surveillants", validators=[], description="texte libre") + batiment = StringField("Bâtiment", description="texte libre") + salle = StringField("Salle", description="texte libre") nb_rangs = SelectField( "nb de places en largeur", coerce=int, @@ -139,19 +130,21 @@ class PlacementForm(FlaskForm): evaluation_id ) choices = [] - for partition in self.groups_tree: - for groupe in self.groups_tree[partition]: + for partition, groupes in self.groups_tree.items(): + for groupe in groupes: if ( groupe == TOUS ): # Affichage et valeur spécifique pour le groupe TOUS - self.tous_id = str(self.groups_tree[partition][groupe]) + self.tous_id = str(groupes[groupe]) choices.append((TOUS, TOUS)) else: groupe_id = str(self.groups_tree[partition][groupe]) - choices.append((groupe_id, "%s (%s)" % (str(groupe), partition))) + choices.append((groupe_id, f"{str(groupe)} ({partition})")) self.groups.choices = choices - # self.groups.default = [TOUS] # Ne fonctionnne pas... (ni dans la déclaration de PlaceForm.groups) - # la réponse [] est de toute façon transposée en [ self.tous_id ] lors du traitement (cas du groupe unique) + # self.groups.default = [TOUS] # Ne fonctionnne pas... + # (ni dans la déclaration de PlaceForm.groups) + # la réponse [] est de toute façon transposée en [ self.tous_id ] + # lors du traitement (cas du groupe unique) class _DistributeurContinu: @@ -227,48 +220,34 @@ class PlacementRunner: self.file_format = form["file_format"].data if len(form["groups"].data) == 0: self.groups_ids = [form.tous_id] - else: # On remplace le mot-clé TOUS le l'identiant de ce groupe + else: # On remplace le mot-clé TOUS par l'identifiant de ce groupe self.groups_ids = [ gid if gid != TOUS else form.tous_id for gid in form["groups"].data ] - self.evaluation = Evaluation.get_evaluation(self.evaluation_id) + evl = Evaluation.get_evaluation(self.evaluation_id) + self.evaluation = evl self.groups = sco_groups.listgroups(self.groups_ids) self.gr_title_filename = sco_groups.listgroups_filename(self.groups) - # gr_title = sco_groups.listgroups_abbrev(d['groups']) self.current_user = current_user - self.moduleimpl_id = self.evaluation.moduleimpl_id - self.moduleimpl: ModuleImpl = ModuleImpl.query.get_or_404(self.moduleimpl_id) - # TODO: à revoir pour utiliser modèle ModuleImpl - self.moduleimpl_data = sco_moduleimpl.moduleimpl_list( - moduleimpl_id=self.moduleimpl_id - )[0] - self.module_data = Module.get_module( - self.moduleimpl_data["module_id"] - ).to_dict() - self.sem = sco_formsemestre.get_formsemestre( - self.moduleimpl_data["formsemestre_id"] - ) - self.evalname = "%s-%s" % ( - self.module_data["code"] or "?", - ( - self.evaluation.date_debut.strftime("%Y-%m-%d_%Hh%M") - if self.evaluation.date_debut - else "" - ), - ) - if self.evaluation.description: + self.moduleimpl_id = evl.moduleimpl_id + self.moduleimpl: ModuleImpl = evl.moduleimpl + self.moduleimpl_data = self.moduleimpl.to_dict() + mod = evl.moduleimpl.module + self.module_data = mod.to_dict() + self.evalname = f"""{mod.code or "?"}-{ + evl.date_debut.strftime("%Y-%m-%d_%Hh%M") if evl.date_debut else ""}""" + if evl.description: self.evaltitre = self.evaluation.description else: self.evaltitre = f"""évaluation{ - self.evaluation.date_debut.strftime(' du %d/%m/%Y à %Hh%M') - if self.evaluation.date_debut else ''}""" + evl.date_debut.strftime(' du ' + scu.DATEATIME_FMT) + if evl.date_debut else ''}""" self.desceval = [ # une liste de chaines: description de l'evaluation - self.sem["titreannee"], - "Module : %s - %s" - % (self.module_data["code"] or "?", self.module_data["abbrev"] or ""), - "Surveillants : %s" % self.surveillants, - "Batiment : %(batiment)s - Salle : %(salle)s" % self.__dict__, - "Controle : %s (coef. %g)" % (self.evaltitre, self.evaluation.coefficient), + evl.moduleimpl.formsemestre.titre_annee(), + f"""Module : {mod.code or "?"} - {evl.moduleimpl.module.abbrev or ""}""", + f"Surveillants : {self.surveillants}", + f"Bâtiment : {self.batiment} - Salle : {self.salle}", + f"Évaluation : {self.evaltitre} (coef. {evl.coefficient:g})", ] self.styles = None self.plan = None @@ -295,26 +274,26 @@ class PlacementRunner: self.listetud = self._build_listetud() self.plan = self._affectation_places() - def _build_listetud(self): - get_all_students = None in [ - g["group_name"] for g in self.groups - ] # tous les etudiants + def _build_listetud(self) -> list[tuple[str, str, int]]: + # tous les etudiants ? + get_all_students = None in [g["group_name"] for g in self.groups] etudid_etats = sco_groups.do_evaluation_listeetuds_groups( self.evaluation_id, self.groups, getallstudents=get_all_students, include_demdef=True, ) - listetud = [] # liste de couples (nom,prenom) + listetud = [] # liste de tuples (nom, prenom, etudid) for etudid, etat in etudid_etats: - # infos identite etudiant (xxx sous-optimal: 1/select par etudiant) - ident = sco_etud.etudident_list(ndb.GetDBConnexion(), {"etudid": etudid})[0] - if etat != "D": - nom = ident["nom"].upper() - prenom = ident["prenom"].lower().capitalize() - etudid = ident["etudid"] - listetud.append((nom, prenom, etudid)) + if etat != scu.DEMISSION: + # infos identite etudiant + etud = Identite.get_etud(etudid) + nom = etud.nom.upper() + prenom = etud.prenom.lower().capitalize() + listetud.append((nom, prenom, etud.id)) + random.shuffle(listetud) + return listetud def _affectation_places(self): @@ -328,7 +307,7 @@ class PlacementRunner: return plan def _production_xls(self): - filename = "placement_%s_%s" % (self.evalname, self.gr_title_filename) + filename = f"placement_{self.evalname}_{self.gr_title_filename}" xls = self._excel_feuille_placement() return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE) @@ -338,10 +317,10 @@ class PlacementRunner: if self.evaluation.date_debut else '-' } - Horaire : {self.evaluation.heure_debut()} à {self.evaluation.heure_fin() }""" - filename = "placement_%(evalname)s_%(gr_title_filename)s" % self.__dict__ + filename = f"placement_{self.evalname}_{self.gr_title_filename}" titles = { "nom": "Nom", - "prenom": "Prenom", + "prenom": "Prénom", "colonne": "Colonne", "ligne": "Ligne", "place": "Place", @@ -369,9 +348,7 @@ class PlacementRunner: columns_ids=columns_ids, rows=rows, filename=filename, - origin="Généré par %s le " % sco_version.SCONAME - + scu.timedate_human_repr() - + "", + origin=f"Généré par {sco_version.SCONAME} le {scu.timedate_human_repr()}", pdf_title=pdf_title, # pdf_shorttitle = '', preferences=sco_preferences.SemPreferences( @@ -476,9 +453,9 @@ class PlacementRunner: } def _titres(self, worksheet): - datetime = time.strftime("%d/%m/%Y a %Hh%M") + date_time = time.strftime(scu.DATEATIME_FMT) worksheet.append_single_cell_row( - "Feuille placement etudiants éditée le %s" % datetime, self.styles["titres"] + f"Feuille placement etudiants éditée le {date_time}", self.styles["titres"] ) for line, desceval in enumerate(self.desceval): if line in [1, 4, 7]: @@ -497,7 +474,7 @@ class PlacementRunner: # entetes colonnes - feuille0 cells = [ws0.make_cell()] for col in range(self.nb_rangs): - cells.append(ws0.make_cell("colonne %s" % (col + 1), self.styles["2b"])) + cells.append(ws0.make_cell(f"colonne {col + 1}", self.styles["2b"])) ws0.append_row(cells) # etudiants - feuille0 @@ -517,7 +494,7 @@ class PlacementRunner: if self.etiquetage == COORD: cell_c = ws0.make_cell("", self.styles["1bb"]) else: - cell_c = ws0.make_cell("place %s" % place, self.styles["1bb"]) + cell_c = ws0.make_cell(f"place {place}", self.styles["1bb"]) place = place + 1 cells_c.append(cell_c) ws0.set_row_dimension_height(row, space / 25) diff --git a/app/templates/scodoc/forms/placement.j2 b/app/templates/scodoc/forms/placement.j2 index ecfe3664..b7e6e582 100644 --- a/app/templates/scodoc/forms/placement.j2 +++ b/app/templates/scodoc/forms/placement.j2 @@ -13,6 +13,7 @@ {% endfor %} </ul> {% endif %} + <span class="help">{{field.description}}</span> </td> </tr> {% endmacro %} @@ -60,6 +61,8 @@ <input id="gr_cancel" type=submit value="Annuler"> </script> </form> + + <div class="help"> <h3>Explications</h3> <ul> <li>préciser les surveillants et la localisation (bâtiment et salle) et indiquer la largeur de la salle (nombre @@ -85,5 +88,6 @@ </ul> </li> </ul> + </div> </div> {% endblock %} \ No newline at end of file diff --git a/sco_version.py b/sco_version.py index d6221591..1dae3244 100644 --- a/sco_version.py +++ b/sco_version.py @@ -3,7 +3,7 @@ "Infos sur version ScoDoc" -SCOVERSION = "9.7.31" +SCOVERSION = "9.7.32" SCONAME = "ScoDoc" -- GitLab