minor changes
This commit is contained in:
parent
0ef822cfd8
commit
b6cc251c94
@ -30,57 +30,50 @@
|
|||||||
Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016
|
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 random
|
||||||
import time
|
import time
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
import wtforms.validators
|
import wtforms.validators
|
||||||
from flask import request, render_template, url_for
|
from flask import request, render_template
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from werkzeug import Response
|
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
|
from openpyxl.styles import PatternFill, Alignment, Border, Side, Font
|
||||||
from wtforms import (
|
from wtforms import (
|
||||||
StringField,
|
StringField,
|
||||||
PasswordField,
|
|
||||||
BooleanField,
|
|
||||||
SubmitField,
|
SubmitField,
|
||||||
SelectField,
|
SelectField,
|
||||||
RadioField,
|
RadioField,
|
||||||
HiddenField,
|
HiddenField,
|
||||||
SelectMultipleField,
|
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.sco_utils as scu
|
||||||
import app.scodoc.notesdb as ndb
|
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_edit_module
|
||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_excel
|
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
|
||||||
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
|
||||||
from app.scodoc import sco_permissions_check
|
from app.scodoc import sco_permissions_check
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc.gen_tables import GenTable
|
||||||
from app.scodoc import sco_saisie_notes
|
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_etud
|
||||||
import sco_version
|
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
|
# _ = lambda x: x # sans babel
|
||||||
_l = _
|
# _l = _
|
||||||
|
|
||||||
COORD = "Coordonnées"
|
COORD = "Coordonnées"
|
||||||
SEQ = "Continue"
|
SEQ = "Continue"
|
||||||
|
|
||||||
|
|
||||||
class PlacementForm(FlaskForm):
|
class PlacementForm(FlaskForm):
|
||||||
|
"""Formulaire pour placement des étudiants en Salle"""
|
||||||
|
|
||||||
TOUS = "Tous"
|
TOUS = "Tous"
|
||||||
evaluation_id = HiddenField("evaluation_id")
|
evaluation_id = HiddenField("evaluation_id")
|
||||||
file_format = RadioField(
|
file_format = RadioField(
|
||||||
@ -112,10 +105,10 @@ class PlacementForm(FlaskForm):
|
|||||||
submit = SubmitField("OK")
|
submit = SubmitField("OK")
|
||||||
|
|
||||||
def set_evaluation_infos(self, evaluation_id):
|
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})
|
eval_data = sco_evaluations.do_evaluation_list({"evaluation_id": evaluation_id})
|
||||||
if not eval_data:
|
if not eval_data:
|
||||||
raise ScoValueError("invalid evaluation_id")
|
raise ScoValueError("invalid evaluation_id")
|
||||||
eval_data = eval_data[0]
|
|
||||||
# groupes
|
# groupes
|
||||||
groups = sco_groups.do_evaluation_listegroupes(
|
groups = sco_groups.do_evaluation_listegroupes(
|
||||||
evaluation_id, include_default=True
|
evaluation_id, include_default=True
|
||||||
@ -123,7 +116,7 @@ class PlacementForm(FlaskForm):
|
|||||||
self.groups_tree = {}
|
self.groups_tree = {}
|
||||||
self.has_groups = False
|
self.has_groups = False
|
||||||
for group in groups:
|
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_id = group["group_id"]
|
||||||
group_name = group["group_name"] or self.TOUS
|
group_name = group["group_name"] or self.TOUS
|
||||||
if partition not in self.groups_tree:
|
if partition not in self.groups_tree:
|
||||||
@ -136,8 +129,8 @@ class PlacementForm(FlaskForm):
|
|||||||
choices = []
|
choices = []
|
||||||
for partition in self.groups_tree:
|
for partition in self.groups_tree:
|
||||||
for groupe in self.groups_tree[partition]:
|
for groupe in self.groups_tree[partition]:
|
||||||
id = str(self.groups_tree[partition][groupe])
|
groupe_id = str(self.groups_tree[partition][groupe])
|
||||||
choices.append((id, "%s (%s)" % (str(groupe), partition)))
|
choices.append((groupe_id, "%s (%s)" % (str(groupe), partition)))
|
||||||
self.groups.choices = choices
|
self.groups.choices = choices
|
||||||
|
|
||||||
|
|
||||||
@ -188,14 +181,16 @@ def placement_eval_selectetuds(evaluation_id):
|
|||||||
"""
|
"""
|
||||||
% runner.__dict__
|
% 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"))
|
# return flask.redirect(url_for("scodoc.index"))
|
||||||
H = [html_sco_header.sco_header(init_jquery_ui=True)]
|
htmls = [
|
||||||
H.append(sco_evaluations.evaluation_describe(evaluation_id=evaluation_id))
|
html_sco_header.sco_header(init_jquery_ui=True),
|
||||||
H.append("<h3>Placement et émargement des étudiants</h3>")
|
sco_evaluations.evaluation_describe(evaluation_id=evaluation_id),
|
||||||
H.append(render_template("scodoc/forms/placement.html", form=form))
|
"<h3>Placement et émargement des étudiants</h3>",
|
||||||
|
render_template("scodoc/forms/placement.html", form=form),
|
||||||
|
]
|
||||||
F = html_sco_header.sco_footer()
|
F = html_sco_header.sco_footer()
|
||||||
return "\n".join(H) + "<p>" + F
|
return "\n".join(htmls) + "<p>" + F
|
||||||
|
|
||||||
|
|
||||||
class PlacementRunner:
|
class PlacementRunner:
|
||||||
@ -235,16 +230,14 @@ class PlacementRunner:
|
|||||||
self.evaltitre = self.eval_data["description"]
|
self.evaltitre = self.eval_data["description"]
|
||||||
else:
|
else:
|
||||||
self.evaltitre = "évaluation du %s" % self.eval_data["jour"]
|
self.evaltitre = "évaluation du %s" % self.eval_data["jour"]
|
||||||
self.desceval = [
|
self.desceval = [ # une liste de chaines: description de l'evaluation
|
||||||
["%s" % self.sem["titreannee"]],
|
"%s" % self.sem["titreannee"],
|
||||||
["Module : %s - %s" % (self.Mod["code"], self.Mod["abbrev"])],
|
"Module : %s - %s" % (self.Mod["code"], self.Mod["abbrev"]),
|
||||||
["Surveillants : %s" % self.surveillants],
|
"Surveillants : %s" % self.surveillants,
|
||||||
["Batiment : %(batiment)s - Salle : %(salle)s" % self.__dict__],
|
"Batiment : %(batiment)s - Salle : %(salle)s" % self.__dict__,
|
||||||
[
|
|
||||||
"Controle : %s (coef. %g)"
|
"Controle : %s (coef. %g)"
|
||||||
% (self.evaltitre, self.eval_data["coefficient"])
|
% (self.evaltitre, self.eval_data["coefficient"]),
|
||||||
],
|
]
|
||||||
] # une liste de liste de chaines: description de l'evaluation
|
|
||||||
|
|
||||||
def check_placement(self):
|
def check_placement(self):
|
||||||
# Check access (admin, respformation, and responsable_id)
|
# Check access (admin, respformation, and responsable_id)
|
||||||
@ -252,7 +245,7 @@ class PlacementRunner:
|
|||||||
self.current_user, self.moduleimpl_id
|
self.current_user, self.moduleimpl_id
|
||||||
)
|
)
|
||||||
|
|
||||||
def _exec_placement(self):
|
def exec_placement(self):
|
||||||
self._repartition()
|
self._repartition()
|
||||||
if self.file_format == "xls":
|
if self.file_format == "xls":
|
||||||
return self._production_xls()
|
return self._production_xls()
|
||||||
@ -271,7 +264,6 @@ class PlacementRunner:
|
|||||||
def _build_listetud(self):
|
def _build_listetud(self):
|
||||||
if None in [g["group_name"] for g in self.groups]: # tous les etudiants
|
if None in [g["group_name"] for g in self.groups]: # tous les etudiants
|
||||||
getallstudents = True
|
getallstudents = True
|
||||||
gr_title_filename = "tous"
|
|
||||||
else:
|
else:
|
||||||
getallstudents = False
|
getallstudents = False
|
||||||
etudids = sco_groups.do_evaluation_listeetuds_groups(
|
etudids = sco_groups.do_evaluation_listeetuds_groups(
|
||||||
@ -310,18 +302,21 @@ class PlacementRunner:
|
|||||||
return plan
|
return plan
|
||||||
|
|
||||||
def _production_xls(self):
|
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()
|
xls = self._excel_feuille_placement()
|
||||||
return sco_excel.send_from_flask(xls, filename)
|
return sco_excel.send_from_flask(xls, filename)
|
||||||
|
|
||||||
def _production_pdf(self):
|
def _production_pdf(self):
|
||||||
pdf_title = self.desceval
|
pdf_title = "<br/>".join(self.desceval)
|
||||||
pdf_title += (
|
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
|
% self.eval_data
|
||||||
)
|
)
|
||||||
breakpoint()
|
filename = "placement_%(evalname)s_%(gr_title_filename)s" % self.__dict__
|
||||||
filename = "placement_%(evalname)s_%(gr_title_filename)s.pdf" % self.__dict__
|
|
||||||
titles = {
|
titles = {
|
||||||
"nom": "Nom",
|
"nom": "Nom",
|
||||||
"prenom": "Prenom",
|
"prenom": "Prenom",
|
||||||
@ -329,7 +324,6 @@ class PlacementRunner:
|
|||||||
"ligne": "Ligne",
|
"ligne": "Ligne",
|
||||||
"place": "Place",
|
"place": "Place",
|
||||||
}
|
}
|
||||||
nb_rangs = int(self.nb_rangs)
|
|
||||||
if self.etiquetage == COORD:
|
if self.etiquetage == COORD:
|
||||||
columns_ids = ["nom", "prenom", "colonne", "ligne"]
|
columns_ids = ["nom", "prenom", "colonne", "ligne"]
|
||||||
else:
|
else:
|
||||||
@ -348,7 +342,6 @@ class PlacementRunner:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rows.append({"nom": etud[0][0], "prenom": etud[0][1], "place": etud[1]})
|
rows.append({"nom": etud[0][0], "prenom": etud[0][1], "place": etud[1]})
|
||||||
|
|
||||||
tab = GenTable(
|
tab = GenTable(
|
||||||
titles=titles,
|
titles=titles,
|
||||||
columns_ids=columns_ids,
|
columns_ids=columns_ids,
|
||||||
@ -359,10 +352,11 @@ class PlacementRunner:
|
|||||||
+ "",
|
+ "",
|
||||||
pdf_title=pdf_title,
|
pdf_title=pdf_title,
|
||||||
# pdf_shorttitle = '',
|
# pdf_shorttitle = '',
|
||||||
preferences=sco_preferences.SemPreferences(self.moduleimpl_data["formsemestre_id"]),
|
preferences=sco_preferences.SemPreferences(
|
||||||
# html_generate_cells=False # la derniere ligne (moyennes) est incomplete
|
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
|
return t
|
||||||
|
|
||||||
def _one_header(self, ws):
|
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):
|
def _titres(self, ws):
|
||||||
dt = time.strftime("%d/%m/%Y a %Hh%M")
|
dt = time.strftime("%d/%m/%Y a %Hh%M")
|
||||||
ws.append_single_cell_row(
|
ws.append_single_cell_row(
|
||||||
@ -476,7 +461,7 @@ class PlacementRunner:
|
|||||||
for line, desceval in enumerate(self.desceval):
|
for line, desceval in enumerate(self.desceval):
|
||||||
if line in [1, 4, 7]:
|
if line in [1, 4, 7]:
|
||||||
ws.append_blank_row()
|
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(
|
ws.append_single_cell_row(
|
||||||
"Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s"
|
"Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s"
|
||||||
% self.eval_data,
|
% self.eval_data,
|
||||||
@ -517,7 +502,9 @@ class PlacementRunner:
|
|||||||
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_b)
|
||||||
ws0.append_row(cells_c)
|
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_b = [ws0.make_cell("", self.styles["2b"])]
|
||||||
cells_c = [ws0.make_cell("", self.styles["2b"])]
|
cells_c = [ws0.make_cell("", self.styles["2b"])]
|
||||||
col = 0
|
col = 0
|
||||||
@ -528,7 +515,7 @@ class PlacementRunner:
|
|||||||
ws0.append_row(cells_c)
|
ws0.append_row(cells_c)
|
||||||
ws0.set_row_dimension_height(row, space / 25)
|
ws0.set_row_dimension_height(row, space / 25)
|
||||||
|
|
||||||
def _next_page(ws):
|
def _next_page(self, ws):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _feuille1(self, ws, maxlines):
|
def _feuille1(self, ws, maxlines):
|
||||||
@ -554,27 +541,28 @@ class PlacementRunner:
|
|||||||
self._headers(ws, nb_listes)
|
self._headers(ws, nb_listes)
|
||||||
# construction liste alphabétique
|
# construction liste alphabétique
|
||||||
# Affichage
|
# Affichage
|
||||||
lines = self._init_lines(maxlines)
|
lines = [[] for _ in range(maxlines)]
|
||||||
line = 0
|
lineno = 0
|
||||||
col = 0
|
col = 0
|
||||||
for etud in sorted(self.plan, key=lambda e: e[0][0]): # tri alphabétique
|
for etud in sorted(self.plan, key=lambda e: e[0][0]): # tri alphabétique
|
||||||
# check for skip of list or page
|
# check for skip of list or page
|
||||||
if col > 0: # add a empty cell between lists
|
if col > 0: # add a empty cell between lists
|
||||||
lines[line].append(ws.make_cell())
|
lines[lineno].append(ws.make_cell())
|
||||||
lines[line].append(ws.make_cell(etud[0][0], self.styles["2l"]))
|
lines[lineno].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(etud[0][1], self.styles["2m1"]))
|
||||||
if self.etiquetage == COORD:
|
if self.etiquetage == COORD:
|
||||||
lines[line].append(ws.make_cell(etud[1][1], self.styles["2m2"]))
|
lines[lineno].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][0], self.styles["2r"]))
|
||||||
else:
|
else:
|
||||||
lines[line].append(ws.make_cell(etud[1], self.styles["2r"]))
|
lines[lineno].append(ws.make_cell(etud[1], self.styles["2r"]))
|
||||||
line = line + 1
|
lineno = lineno + 1
|
||||||
if line >= maxlines: # fin de liste
|
if lineno >= maxlines: # fin de liste
|
||||||
col = col + 1
|
col = col + 1
|
||||||
line = 0
|
lineno = 0
|
||||||
if col >= maxlistes: # fin de page
|
if col >= maxlistes: # fin de page
|
||||||
self._write_lines(ws, lines)
|
for line_cells in lines:
|
||||||
lines = self._init_lines(maxlines)
|
ws.append_row(line_cells)
|
||||||
|
lines = [[] for _ in range(maxlines)]
|
||||||
col = 0
|
col = 0
|
||||||
ws.append_blank_row()
|
ws.append_blank_row()
|
||||||
nb_etu_restant -= maxlistes * maxlines
|
nb_etu_restant -= maxlistes * maxlines
|
||||||
@ -582,7 +570,8 @@ class PlacementRunner:
|
|||||||
maxlistes, nb_etu_restant // maxlines + 1
|
maxlistes, nb_etu_restant // maxlines + 1
|
||||||
) # nombre de colonnes dans la page
|
) # nombre de colonnes dans la page
|
||||||
self._headers(ws, nb_listes)
|
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):
|
def _excel_feuille_placement(self):
|
||||||
"""Genere feuille excel pour placement des etudiants.
|
"""Genere feuille excel pour placement des etudiants.
|
||||||
|
Loading…
Reference in New Issue
Block a user