diff --git a/app/scodoc/sco_placement.py b/app/scodoc/sco_placement.py index 32f89437..acc888ee 100644 --- a/app/scodoc/sco_placement.py +++ b/app/scodoc/sco_placement.py @@ -30,57 +30,50 @@ Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016 """ -import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error import random import time from copy import copy import wtforms.validators -from flask import request, render_template, url_for +from flask import request, render_template from flask_login import current_user -from werkzeug import Response from flask_wtf import FlaskForm +from openpyxl.styles import PatternFill, Alignment, Border, Side, Font from wtforms import ( StringField, - PasswordField, - BooleanField, SubmitField, SelectField, RadioField, HiddenField, SelectMultipleField, - validators, ) -from wtforms.validators import ValidationError, DataRequired, Email, EqualTo - -from app.scodoc.sco_exceptions import ScoValueError import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb -from app.scodoc import html_sco_header +from app import ScoValueError +from app.scodoc import html_sco_header, sco_preferences from app.scodoc import sco_edit_module 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_formsemestre_inscriptions from app.scodoc import sco_groups from app.scodoc import sco_moduleimpl from app.scodoc import sco_permissions_check -from app.scodoc import sco_preferences -from app.scodoc import sco_saisie_notes +from app.scodoc.gen_tables import GenTable from app.scodoc import sco_etud import sco_version -from app.scodoc.gen_tables import GenTable -from app.scodoc.sco_excel import * # XXX à vérifier -from app.scodoc.TrivialFormulator import TrivialFormulator -_ = lambda x: x # sans babel -_l = _ +# _ = lambda x: x # sans babel +# _l = _ COORD = "Coordonnées" SEQ = "Continue" class PlacementForm(FlaskForm): + """Formulaire pour placement des étudiants en Salle""" + TOUS = "Tous" evaluation_id = HiddenField("evaluation_id") file_format = RadioField( @@ -112,10 +105,10 @@ class PlacementForm(FlaskForm): submit = SubmitField("OK") def set_evaluation_infos(self, evaluation_id): + """Initialise les données du formulaire avec les données de l'évaluation.""" eval_data = sco_evaluations.do_evaluation_list({"evaluation_id": evaluation_id}) if not eval_data: raise ScoValueError("invalid evaluation_id") - eval_data = eval_data[0] # groupes groups = sco_groups.do_evaluation_listegroupes( evaluation_id, include_default=True @@ -123,7 +116,7 @@ class PlacementForm(FlaskForm): self.groups_tree = {} self.has_groups = False for group in groups: - partition = group["partition_name"] or self.TOUS # TODO check required + partition = group["partition_name"] or self.TOUS group_id = group["group_id"] group_name = group["group_name"] or self.TOUS if partition not in self.groups_tree: @@ -136,8 +129,8 @@ class PlacementForm(FlaskForm): choices = [] for partition in self.groups_tree: for groupe in self.groups_tree[partition]: - id = str(self.groups_tree[partition][groupe]) - choices.append((id, "%s (%s)" % (str(groupe), partition))) + groupe_id = str(self.groups_tree[partition][groupe]) + choices.append((groupe_id, "%s (%s)" % (str(groupe), partition))) self.groups.choices = choices @@ -188,14 +181,16 @@ def placement_eval_selectetuds(evaluation_id): """ % runner.__dict__ ) - return runner._exec_placement() # calcul et generation du fichier + return runner.exec_placement() # calcul et generation du fichier # return flask.redirect(url_for("scodoc.index")) - H = [html_sco_header.sco_header(init_jquery_ui=True)] - H.append(sco_evaluations.evaluation_describe(evaluation_id=evaluation_id)) - H.append("

Placement et émargement des étudiants

") - H.append(render_template("scodoc/forms/placement.html", form=form)) + htmls = [ + html_sco_header.sco_header(init_jquery_ui=True), + sco_evaluations.evaluation_describe(evaluation_id=evaluation_id), + "

Placement et émargement des étudiants

", + render_template("scodoc/forms/placement.html", form=form), + ] F = html_sco_header.sco_footer() - return "\n".join(H) + "

" + F + return "\n".join(htmls) + "

" + F class PlacementRunner: @@ -235,16 +230,14 @@ class PlacementRunner: self.evaltitre = self.eval_data["description"] else: self.evaltitre = "évaluation du %s" % self.eval_data["jour"] - self.desceval = [ - ["%s" % self.sem["titreannee"]], - ["Module : %s - %s" % (self.Mod["code"], self.Mod["abbrev"])], - ["Surveillants : %s" % self.surveillants], - ["Batiment : %(batiment)s - Salle : %(salle)s" % self.__dict__], - [ - "Controle : %s (coef. %g)" - % (self.evaltitre, self.eval_data["coefficient"]) - ], - ] # une liste de liste de chaines: description de l'evaluation + self.desceval = [ # une liste de chaines: description de l'evaluation + "%s" % self.sem["titreannee"], + "Module : %s - %s" % (self.Mod["code"], self.Mod["abbrev"]), + "Surveillants : %s" % self.surveillants, + "Batiment : %(batiment)s - Salle : %(salle)s" % self.__dict__, + "Controle : %s (coef. %g)" + % (self.evaltitre, self.eval_data["coefficient"]), + ] def check_placement(self): # Check access (admin, respformation, and responsable_id) @@ -252,7 +245,7 @@ class PlacementRunner: self.current_user, self.moduleimpl_id ) - def _exec_placement(self): + def exec_placement(self): self._repartition() if self.file_format == "xls": return self._production_xls() @@ -271,7 +264,6 @@ class PlacementRunner: def _build_listetud(self): if None in [g["group_name"] for g in self.groups]: # tous les etudiants getallstudents = True - gr_title_filename = "tous" else: getallstudents = False etudids = sco_groups.do_evaluation_listeetuds_groups( @@ -310,18 +302,21 @@ class PlacementRunner: return plan def _production_xls(self): - filename = "placement_%s_%s%s" % (self.evalname, self.gr_title_filename, scu.XLSX_SUFFIX) + filename = "placement_%s_%s%s" % ( + self.evalname, + self.gr_title_filename, + scu.XLSX_SUFFIX, + ) xls = self._excel_feuille_placement() return sco_excel.send_from_flask(xls, filename) def _production_pdf(self): - pdf_title = self.desceval + pdf_title = "
".join(self.desceval) pdf_title += ( - "Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s" + "\nDate : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s" % self.eval_data ) - breakpoint() - filename = "placement_%(evalname)s_%(gr_title_filename)s.pdf" % self.__dict__ + filename = "placement_%(evalname)s_%(gr_title_filename)s" % self.__dict__ titles = { "nom": "Nom", "prenom": "Prenom", @@ -329,7 +324,6 @@ class PlacementRunner: "ligne": "Ligne", "place": "Place", } - nb_rangs = int(self.nb_rangs) if self.etiquetage == COORD: columns_ids = ["nom", "prenom", "colonne", "ligne"] else: @@ -348,7 +342,6 @@ class PlacementRunner: ) else: rows.append({"nom": etud[0][0], "prenom": etud[0][1], "place": etud[1]}) - tab = GenTable( titles=titles, columns_ids=columns_ids, @@ -359,10 +352,11 @@ class PlacementRunner: + "", pdf_title=pdf_title, # pdf_shorttitle = '', - preferences=sco_preferences.SemPreferences(self.moduleimpl_data["formsemestre_id"]), - # html_generate_cells=False # la derniere ligne (moyennes) est incomplete + preferences=sco_preferences.SemPreferences( + self.moduleimpl_data["formsemestre_id"] + ), ) - t = tab.make_page(format="pdf", with_html_headers=False, REQUEST=REQUEST) + t = tab.make_page(format="pdf", with_html_headers=False) return t def _one_header(self, ws): @@ -459,15 +453,6 @@ class PlacementRunner: ), } - def _init_lines(self, maxlines): - return [ - [] for _ in range(maxlines) - ] # lines[no_ligne] -> liste des cellules de la ligne (no_lignes de 1..maxlines - - def _write_lines(self, ws, lines): - for line in lines: - ws.append_row(line) - def _titres(self, ws): dt = time.strftime("%d/%m/%Y a %Hh%M") ws.append_single_cell_row( @@ -476,7 +461,7 @@ class PlacementRunner: for line, desceval in enumerate(self.desceval): if line in [1, 4, 7]: ws.append_blank_row() - ws.append_single_cell_row(desceval[0], self.styles["titres"]) + ws.append_single_cell_row(desceval, self.styles["titres"]) ws.append_single_cell_row( "Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s" % self.eval_data, @@ -514,10 +499,12 @@ class PlacementRunner: row += 3 col += 1 if col == self.nb_rangs: # On a fini la rangée courante - ws0.append_row(cells_a) # on affiche les 3 lignes construites + ws0.append_row(cells_a) # on affiche les 3 lignes construites ws0.append_row(cells_b) ws0.append_row(cells_c) - cells_a = [ws0.make_cell(rang, self.styles["2b"])] # on réinitialise les 3 lignes + cells_a = [ + ws0.make_cell(rang, self.styles["2b"]) + ] # on réinitialise les 3 lignes cells_b = [ws0.make_cell("", self.styles["2b"])] cells_c = [ws0.make_cell("", self.styles["2b"])] col = 0 @@ -528,7 +515,7 @@ class PlacementRunner: ws0.append_row(cells_c) ws0.set_row_dimension_height(row, space / 25) - def _next_page(ws): + def _next_page(self, ws): pass def _feuille1(self, ws, maxlines): @@ -554,27 +541,28 @@ class PlacementRunner: self._headers(ws, nb_listes) # construction liste alphabétique # Affichage - lines = self._init_lines(maxlines) - line = 0 + lines = [[] for _ in range(maxlines)] + lineno = 0 col = 0 for etud in sorted(self.plan, key=lambda e: e[0][0]): # tri alphabétique # check for skip of list or page if col > 0: # add a empty cell between lists - lines[line].append(ws.make_cell()) - lines[line].append(ws.make_cell(etud[0][0], self.styles["2l"])) - lines[line].append(ws.make_cell(etud[0][1], self.styles["2m1"])) + lines[lineno].append(ws.make_cell()) + lines[lineno].append(ws.make_cell(etud[0][0], self.styles["2l"])) + lines[lineno].append(ws.make_cell(etud[0][1], self.styles["2m1"])) if self.etiquetage == COORD: - lines[line].append(ws.make_cell(etud[1][1], self.styles["2m2"])) - lines[line].append(ws.make_cell(etud[1][0], self.styles["2r"])) + lines[lineno].append(ws.make_cell(etud[1][1], self.styles["2m2"])) + lines[lineno].append(ws.make_cell(etud[1][0], self.styles["2r"])) else: - lines[line].append(ws.make_cell(etud[1], self.styles["2r"])) - line = line + 1 - if line >= maxlines: # fin de liste + lines[lineno].append(ws.make_cell(etud[1], self.styles["2r"])) + lineno = lineno + 1 + if lineno >= maxlines: # fin de liste col = col + 1 - line = 0 + lineno = 0 if col >= maxlistes: # fin de page - self._write_lines(ws, lines) - lines = self._init_lines(maxlines) + for line_cells in lines: + ws.append_row(line_cells) + lines = [[] for _ in range(maxlines)] col = 0 ws.append_blank_row() nb_etu_restant -= maxlistes * maxlines @@ -582,7 +570,8 @@ class PlacementRunner: maxlistes, nb_etu_restant // maxlines + 1 ) # nombre de colonnes dans la page self._headers(ws, nb_listes) - self._write_lines(ws, lines) + for line_cells in lines: + ws.append_row(line_cells) def _excel_feuille_placement(self): """Genere feuille excel pour placement des etudiants. @@ -610,7 +599,7 @@ class PlacementRunner: ws0.set_column_dimension_width("A", 750 * column_width_ratio) for col in range(nb_rangs): ws0.set_column_dimension_width( - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[col + 1 : col + 2], width + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[col + 1: col + 2], width ) SheetName1 = "Positions"