forked from ScoDoc/ScoDoc
Modernisation code démission/défaillance...
This commit is contained in:
parent
9d29af3ac7
commit
a81b86efff
File diff suppressed because it is too large
Load Diff
|
@ -1,163 +1,171 @@
|
|||
# -*- coding: UTF-8 -*
|
||||
|
||||
"""Notes, décisions de jury, évènements scolaires
|
||||
"""
|
||||
|
||||
from app import db
|
||||
from app.models import SHORT_STR_LEN
|
||||
from app.models import CODE_STR_LEN
|
||||
from app.models.events import Scolog
|
||||
|
||||
|
||||
class ScolarFormSemestreValidation(db.Model):
|
||||
"""Décisions de jury"""
|
||||
|
||||
__tablename__ = "scolar_formsemestre_validation"
|
||||
# Assure unicité de la décision:
|
||||
__table_args__ = (db.UniqueConstraint("etudid", "formsemestre_id", "ue_id"),)
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
formsemestre_validation_id = db.synonym("id")
|
||||
etudid = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("identite.id", ondelete="CASCADE"),
|
||||
index=True,
|
||||
)
|
||||
formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
index=True,
|
||||
)
|
||||
ue_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_ue.id"),
|
||||
index=True,
|
||||
)
|
||||
code = db.Column(db.String(CODE_STR_LEN), nullable=False, index=True)
|
||||
# NULL pour les UE, True|False pour les semestres:
|
||||
assidu = db.Column(db.Boolean)
|
||||
event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||
# NULL sauf si compense un semestre: (pas utilisé pour BUT)
|
||||
compense_formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
)
|
||||
moy_ue = db.Column(db.Float)
|
||||
# (normalement NULL) indice du semestre, utile seulement pour
|
||||
# UE "antérieures" et si la formation définit des UE utilisées
|
||||
# dans plusieurs semestres (cas R&T IUTV v2)
|
||||
semestre_id = db.Column(db.Integer)
|
||||
# Si UE validée dans le cursus d'un autre etablissement
|
||||
is_external = db.Column(
|
||||
db.Boolean, default=False, server_default="false", index=True
|
||||
)
|
||||
|
||||
ue = db.relationship("UniteEns", lazy="select", uselist=False)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}({self.formsemestre_id}, {self.etudid}, code={self.code}, ue={self.ue}, moy_ue={self.moy_ue})"
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
d = dict(self.__dict__)
|
||||
d.pop("_sa_instance_state", None)
|
||||
return d
|
||||
|
||||
|
||||
class ScolarAutorisationInscription(db.Model):
|
||||
"""Autorisation d'inscription dans un semestre"""
|
||||
|
||||
__tablename__ = "scolar_autorisation_inscription"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
autorisation_inscription_id = db.synonym("id")
|
||||
|
||||
etudid = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("identite.id", ondelete="CASCADE"),
|
||||
)
|
||||
formation_code = db.Column(db.String(SHORT_STR_LEN), nullable=False)
|
||||
# Indice du semestre où on peut s'inscrire:
|
||||
semestre_id = db.Column(db.Integer)
|
||||
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||
origin_formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
d = dict(self.__dict__)
|
||||
d.pop("_sa_instance_state", None)
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
def autorise_etud(
|
||||
cls,
|
||||
etudid: int,
|
||||
formation_code: str,
|
||||
origin_formsemestre_id: int,
|
||||
semestre_id: int,
|
||||
):
|
||||
"""Enregistre une autorisation, remplace celle émanant du même semestre si elle existe."""
|
||||
cls.delete_autorisation_etud(etudid, origin_formsemestre_id)
|
||||
autorisation = cls(
|
||||
etudid=etudid,
|
||||
formation_code=formation_code,
|
||||
origin_formsemestre_id=origin_formsemestre_id,
|
||||
semestre_id=semestre_id,
|
||||
)
|
||||
db.session.add(autorisation)
|
||||
Scolog.logdb("autorise_etud", etudid=etudid, msg=f"passage vers S{semestre_id}")
|
||||
|
||||
@classmethod
|
||||
def delete_autorisation_etud(
|
||||
cls,
|
||||
etudid: int,
|
||||
origin_formsemestre_id: int,
|
||||
):
|
||||
"""Efface les autorisations de cette étudiant venant du sem. origine"""
|
||||
autorisations = cls.query.filter_by(
|
||||
etudid=etudid, origin_formsemestre_id=origin_formsemestre_id
|
||||
)
|
||||
for autorisation in autorisations:
|
||||
db.session.delete(autorisation)
|
||||
Scolog.logdb(
|
||||
"autorise_etud",
|
||||
etudid=etudid,
|
||||
msg=f"annule passage vers S{autorisation.semestre_id}",
|
||||
)
|
||||
db.session.flush()
|
||||
|
||||
|
||||
class ScolarEvent(db.Model):
|
||||
"""Evenement dans le parcours scolaire d'un étudiant"""
|
||||
|
||||
__tablename__ = "scolar_events"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
event_id = db.synonym("id")
|
||||
etudid = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("identite.id", ondelete="CASCADE"),
|
||||
)
|
||||
event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||
formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
)
|
||||
ue_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_ue.id"),
|
||||
)
|
||||
# 'CREATION', 'INSCRIPTION', 'DEMISSION',
|
||||
# 'AUT_RED', 'EXCLUS', 'VALID_UE', 'VALID_SEM'
|
||||
# 'ECHEC_SEM'
|
||||
# 'UTIL_COMPENSATION'
|
||||
event_type = db.Column(db.String(SHORT_STR_LEN))
|
||||
# Semestre compensé par formsemestre_id:
|
||||
comp_formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
d = dict(self.__dict__)
|
||||
d.pop("_sa_instance_state", None)
|
||||
return d
|
||||
# -*- coding: UTF-8 -*
|
||||
|
||||
"""Notes, décisions de jury, évènements scolaires
|
||||
"""
|
||||
|
||||
from app import db
|
||||
from app.models import SHORT_STR_LEN
|
||||
from app.models import CODE_STR_LEN
|
||||
from app.models.events import Scolog
|
||||
|
||||
|
||||
class ScolarFormSemestreValidation(db.Model):
|
||||
"""Décisions de jury"""
|
||||
|
||||
__tablename__ = "scolar_formsemestre_validation"
|
||||
# Assure unicité de la décision:
|
||||
__table_args__ = (db.UniqueConstraint("etudid", "formsemestre_id", "ue_id"),)
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
formsemestre_validation_id = db.synonym("id")
|
||||
etudid = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("identite.id", ondelete="CASCADE"),
|
||||
index=True,
|
||||
)
|
||||
formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
index=True,
|
||||
)
|
||||
ue_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_ue.id"),
|
||||
index=True,
|
||||
)
|
||||
code = db.Column(db.String(CODE_STR_LEN), nullable=False, index=True)
|
||||
# NULL pour les UE, True|False pour les semestres:
|
||||
assidu = db.Column(db.Boolean)
|
||||
event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||
# NULL sauf si compense un semestre: (pas utilisé pour BUT)
|
||||
compense_formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
)
|
||||
moy_ue = db.Column(db.Float)
|
||||
# (normalement NULL) indice du semestre, utile seulement pour
|
||||
# UE "antérieures" et si la formation définit des UE utilisées
|
||||
# dans plusieurs semestres (cas R&T IUTV v2)
|
||||
semestre_id = db.Column(db.Integer)
|
||||
# Si UE validée dans le cursus d'un autre etablissement
|
||||
is_external = db.Column(
|
||||
db.Boolean, default=False, server_default="false", index=True
|
||||
)
|
||||
|
||||
ue = db.relationship("UniteEns", lazy="select", uselist=False)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}({self.formsemestre_id}, {self.etudid}, code={self.code}, ue={self.ue}, moy_ue={self.moy_ue})"
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
d = dict(self.__dict__)
|
||||
d.pop("_sa_instance_state", None)
|
||||
return d
|
||||
|
||||
|
||||
class ScolarAutorisationInscription(db.Model):
|
||||
"""Autorisation d'inscription dans un semestre"""
|
||||
|
||||
__tablename__ = "scolar_autorisation_inscription"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
autorisation_inscription_id = db.synonym("id")
|
||||
|
||||
etudid = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("identite.id", ondelete="CASCADE"),
|
||||
)
|
||||
formation_code = db.Column(db.String(SHORT_STR_LEN), nullable=False)
|
||||
# Indice du semestre où on peut s'inscrire:
|
||||
semestre_id = db.Column(db.Integer)
|
||||
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||
origin_formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
d = dict(self.__dict__)
|
||||
d.pop("_sa_instance_state", None)
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
def autorise_etud(
|
||||
cls,
|
||||
etudid: int,
|
||||
formation_code: str,
|
||||
origin_formsemestre_id: int,
|
||||
semestre_id: int,
|
||||
):
|
||||
"""Enregistre une autorisation, remplace celle émanant du même semestre si elle existe."""
|
||||
cls.delete_autorisation_etud(etudid, origin_formsemestre_id)
|
||||
autorisation = cls(
|
||||
etudid=etudid,
|
||||
formation_code=formation_code,
|
||||
origin_formsemestre_id=origin_formsemestre_id,
|
||||
semestre_id=semestre_id,
|
||||
)
|
||||
db.session.add(autorisation)
|
||||
Scolog.logdb("autorise_etud", etudid=etudid, msg=f"passage vers S{semestre_id}")
|
||||
|
||||
@classmethod
|
||||
def delete_autorisation_etud(
|
||||
cls,
|
||||
etudid: int,
|
||||
origin_formsemestre_id: int,
|
||||
):
|
||||
"""Efface les autorisations de cette étudiant venant du sem. origine"""
|
||||
autorisations = cls.query.filter_by(
|
||||
etudid=etudid, origin_formsemestre_id=origin_formsemestre_id
|
||||
)
|
||||
for autorisation in autorisations:
|
||||
db.session.delete(autorisation)
|
||||
Scolog.logdb(
|
||||
"autorise_etud",
|
||||
etudid=etudid,
|
||||
msg=f"annule passage vers S{autorisation.semestre_id}",
|
||||
)
|
||||
db.session.flush()
|
||||
|
||||
|
||||
class ScolarEvent(db.Model):
|
||||
"""Evenement dans le parcours scolaire d'un étudiant"""
|
||||
|
||||
__tablename__ = "scolar_events"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
event_id = db.synonym("id")
|
||||
etudid = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("identite.id", ondelete="CASCADE"),
|
||||
)
|
||||
event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||
formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
)
|
||||
ue_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_ue.id"),
|
||||
)
|
||||
# 'CREATION', 'INSCRIPTION', 'DEMISSION',
|
||||
# 'AUT_RED', 'EXCLUS', 'VALID_UE', 'VALID_SEM'
|
||||
# 'ECHEC_SEM'
|
||||
# 'UTIL_COMPENSATION'
|
||||
event_type = db.Column(db.String(SHORT_STR_LEN))
|
||||
# Semestre compensé par formsemestre_id:
|
||||
comp_formsemestre_id = db.Column(
|
||||
db.Integer,
|
||||
db.ForeignKey("notes_formsemestre.id"),
|
||||
)
|
||||
etud = db.relationship("Identite", lazy="select", backref="events", uselist=False)
|
||||
formsemestre = db.relationship(
|
||||
"FormSemestre", lazy="select", uselist=False, foreign_keys=[formsemestre_id]
|
||||
)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"as a dict"
|
||||
d = dict(self.__dict__)
|
||||
d.pop("_sa_instance_state", None)
|
||||
return d
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.__class__.__name__}({self.event_type}, {self.event_date.isoformat()}, {self.formsemestre})"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -117,7 +117,7 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
|
|||
# Les autres situations (eg redoublements en changeant d'établissement)
|
||||
# doivent être gérées par les validations de semestres "antérieurs"
|
||||
insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
|
||||
args={"etudid": etudid, "etat": "I"}
|
||||
args={"etudid": etudid, "etat": scu.INSCRIT}
|
||||
)
|
||||
semlist = [sco_formsemestre.get_formsemestre(i["formsemestre_id"]) for i in insem]
|
||||
existing_semestre_ids = {s["semestre_id"] for s in semlist}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -308,9 +308,9 @@ def get_group_infos(group_id, etat=None): # was _getlisteetud
|
|||
# add human readable description of state:
|
||||
nbdem = 0
|
||||
for t in members:
|
||||
if t["etat"] == "I":
|
||||
if t["etat"] == scu.INSCRIT:
|
||||
t["etath"] = "" # etudiant inscrit, ne l'indique pas dans la liste HTML
|
||||
elif t["etat"] == "D":
|
||||
elif t["etat"] == scu.DEMISSION:
|
||||
events = sco_etud.scolar_events_list(
|
||||
cnx,
|
||||
args={
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,235 +1,235 @@
|
|||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Emmanuel Viennet emmanuel.viennet@gmail.com
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""Extraction de données pour poursuites d'études
|
||||
|
||||
Recapitule tous les semestres validés dans une feuille excel.
|
||||
"""
|
||||
import collections
|
||||
|
||||
from flask import url_for, g, request
|
||||
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import FormSemestre
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_cache
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_etud
|
||||
import sco_version
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.sco_codes_parcours import code_semestre_validant, code_semestre_attente
|
||||
|
||||
|
||||
def etud_get_poursuite_info(sem, etud):
|
||||
"""{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] }"""
|
||||
I = {}
|
||||
I.update(etud) # copie nom, prenom, civilite, ...
|
||||
|
||||
# Now add each semester, starting from the first one
|
||||
semlist = []
|
||||
current_id = sem["semestre_id"]
|
||||
for sem_id in range(1, current_id + 1):
|
||||
sem_descr = None
|
||||
for s in etud["sems"]:
|
||||
if s["semestre_id"] == sem_id:
|
||||
etudid = etud["etudid"]
|
||||
formsemestre = FormSemestre.query.get_or_404(s["formsemestre_id"])
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||
dec = nt.get_etud_decision_sem(etudid)
|
||||
# Moyennes et rangs des UE
|
||||
ues = nt.get_ues_stat_dict(filter_sport=True)
|
||||
moy_ues = []
|
||||
for ue in ues:
|
||||
ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"])
|
||||
if ue_status:
|
||||
moy_ues.append(
|
||||
(
|
||||
ue["acronyme"],
|
||||
scu.fmt_note(
|
||||
nt.get_etud_ue_status(etudid, ue["ue_id"])["moy"]
|
||||
),
|
||||
)
|
||||
)
|
||||
else:
|
||||
moy_ues.append((ue["acronyme"], ""))
|
||||
rg_ues = [
|
||||
("rang_" + ue["acronyme"], nt.ue_rangs[ue["ue_id"]][0][etudid])
|
||||
for ue in ues
|
||||
]
|
||||
|
||||
# Moyennes et rang des modules
|
||||
modimpls = nt.get_modimpls_dict() # recupération des modules
|
||||
modules = []
|
||||
rangs = []
|
||||
for ue in ues: # on parcourt chaque UE
|
||||
for modimpl in modimpls: # dans chaque UE les modules
|
||||
if modimpl["module"]["ue_id"] == ue["ue_id"]:
|
||||
codeModule = modimpl["module"]["code"] or ""
|
||||
noteModule = scu.fmt_note(
|
||||
nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)
|
||||
)
|
||||
if noteModule != "NI": # si étudiant inscrit au module
|
||||
if nt.mod_rangs is not None:
|
||||
rangModule = nt.mod_rangs[modimpl["moduleimpl_id"]][
|
||||
0
|
||||
][etudid]
|
||||
else:
|
||||
rangModule = ""
|
||||
modules.append([codeModule, noteModule])
|
||||
rangs.append(["rang_" + codeModule, rangModule])
|
||||
|
||||
# Absences
|
||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, nt.sem)
|
||||
if (
|
||||
dec
|
||||
and not sem_descr # not sem_descr pour ne prendre que le semestre validé le plus récent
|
||||
and (
|
||||
code_semestre_validant(dec["code"])
|
||||
or code_semestre_attente(dec["code"])
|
||||
)
|
||||
and nt.get_etud_etat(etudid) == "I"
|
||||
):
|
||||
d = [
|
||||
("moy", scu.fmt_note(nt.get_etud_moy_gen(etudid))),
|
||||
("moy_promo", scu.fmt_note(nt.moy_moy)),
|
||||
("rang", nt.get_etud_rang(etudid)),
|
||||
("effectif", len(nt.T)),
|
||||
("date_debut", s["date_debut"]),
|
||||
("date_fin", s["date_fin"]),
|
||||
("periode", "%s - %s" % (s["mois_debut"], s["mois_fin"])),
|
||||
("AbsNonJust", nbabs - nbabsjust),
|
||||
("AbsJust", nbabsjust),
|
||||
]
|
||||
d += (
|
||||
moy_ues + rg_ues + modules + rangs
|
||||
) # ajout des 2 champs notes des modules et classement dans chaque module
|
||||
sem_descr = collections.OrderedDict(d)
|
||||
if not sem_descr:
|
||||
sem_descr = collections.OrderedDict(
|
||||
[
|
||||
("moy", ""),
|
||||
("moy_promo", ""),
|
||||
("rang", ""),
|
||||
("effectif", ""),
|
||||
("date_debut", ""),
|
||||
("date_fin", ""),
|
||||
("periode", ""),
|
||||
]
|
||||
)
|
||||
sem_descr["semestre_id"] = sem_id
|
||||
semlist.append(sem_descr)
|
||||
|
||||
I["semlist"] = semlist
|
||||
return I
|
||||
|
||||
|
||||
def _flatten_info(info):
|
||||
# met la liste des infos semestres "a plat"
|
||||
# S1_moy, S1_rang, ..., S2_moy, ...
|
||||
ids = []
|
||||
for s in info["semlist"]:
|
||||
for k, v in s.items():
|
||||
if k != "semestre_id":
|
||||
label = "S%s_%s" % (s["semestre_id"], k)
|
||||
info[label] = v
|
||||
ids.append(label)
|
||||
return ids
|
||||
|
||||
|
||||
def _getEtudInfoGroupes(group_ids, etat=None):
|
||||
"""liste triée d'infos (dict) sur les etudiants du groupe indiqué.
|
||||
Attention: lent, car plusieurs requetes SQL par etudiant !
|
||||
"""
|
||||
etuds = []
|
||||
for group_id in group_ids:
|
||||
members = sco_groups.get_group_members(group_id, etat=etat)
|
||||
for m in members:
|
||||
etud = sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0]
|
||||
etuds.append(etud)
|
||||
|
||||
return etuds
|
||||
|
||||
|
||||
def formsemestre_poursuite_report(formsemestre_id, format="html"):
|
||||
"""Table avec informations "poursuite" """
|
||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||
etuds = _getEtudInfoGroupes([sco_groups.get_default_group(formsemestre_id)])
|
||||
|
||||
infos = []
|
||||
ids = []
|
||||
for etud in etuds:
|
||||
fiche_url = url_for(
|
||||
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etud["etudid"]
|
||||
)
|
||||
etud["_nom_target"] = fiche_url
|
||||
etud["_prenom_target"] = fiche_url
|
||||
etud["_nom_td_attrs"] = 'id="%s" class="etudinfo"' % (etud["etudid"])
|
||||
info = etud_get_poursuite_info(sem, etud)
|
||||
idd = _flatten_info(info)
|
||||
# On recupere la totalite des UEs dans ids
|
||||
for id in idd:
|
||||
if id not in ids:
|
||||
ids += [id]
|
||||
infos.append(info)
|
||||
#
|
||||
column_ids = (
|
||||
("civilite_str", "nom", "prenom", "annee", "date_naissance")
|
||||
+ tuple(ids)
|
||||
+ ("debouche",)
|
||||
)
|
||||
titles = {}
|
||||
for c in column_ids:
|
||||
titles[c] = c
|
||||
tab = GenTable(
|
||||
titles=titles,
|
||||
columns_ids=column_ids,
|
||||
rows=infos,
|
||||
# html_col_width='4em',
|
||||
html_sortable=True,
|
||||
html_class="table_leftalign table_listegroupe",
|
||||
pdf_link=False, # pas d'export pdf
|
||||
preferences=sco_preferences.SemPreferences(formsemestre_id),
|
||||
)
|
||||
tab.filename = scu.make_filename("poursuite " + sem["titreannee"])
|
||||
|
||||
tab.origin = (
|
||||
"Généré par %s le " % sco_version.SCONAME + scu.timedate_human_repr() + ""
|
||||
)
|
||||
tab.caption = "Récapitulatif %s." % sem["titreannee"]
|
||||
tab.html_caption = "Récapitulatif %s." % sem["titreannee"]
|
||||
tab.base_url = "%s?formsemestre_id=%s" % (request.base_url, formsemestre_id)
|
||||
return tab.make_page(
|
||||
title="""<h2 class="formsemestre">Poursuite d'études</h2>""",
|
||||
init_qtip=True,
|
||||
javascripts=["js/etud_info.js"],
|
||||
format=format,
|
||||
with_html_headers=True,
|
||||
)
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Emmanuel Viennet emmanuel.viennet@gmail.com
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""Extraction de données pour poursuites d'études
|
||||
|
||||
Recapitule tous les semestres validés dans une feuille excel.
|
||||
"""
|
||||
import collections
|
||||
|
||||
from flask import url_for, g, request
|
||||
|
||||
from app.comp import res_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import FormSemestre
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_cache
|
||||
from app.scodoc import sco_formsemestre
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_etud
|
||||
import sco_version
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.sco_codes_parcours import code_semestre_validant, code_semestre_attente
|
||||
|
||||
|
||||
def etud_get_poursuite_info(sem, etud):
|
||||
"""{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] }"""
|
||||
I = {}
|
||||
I.update(etud) # copie nom, prenom, civilite, ...
|
||||
|
||||
# Now add each semester, starting from the first one
|
||||
semlist = []
|
||||
current_id = sem["semestre_id"]
|
||||
for sem_id in range(1, current_id + 1):
|
||||
sem_descr = None
|
||||
for s in etud["sems"]:
|
||||
if s["semestre_id"] == sem_id:
|
||||
etudid = etud["etudid"]
|
||||
formsemestre = FormSemestre.query.get_or_404(s["formsemestre_id"])
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||
dec = nt.get_etud_decision_sem(etudid)
|
||||
# Moyennes et rangs des UE
|
||||
ues = nt.get_ues_stat_dict(filter_sport=True)
|
||||
moy_ues = []
|
||||
for ue in ues:
|
||||
ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"])
|
||||
if ue_status:
|
||||
moy_ues.append(
|
||||
(
|
||||
ue["acronyme"],
|
||||
scu.fmt_note(
|
||||
nt.get_etud_ue_status(etudid, ue["ue_id"])["moy"]
|
||||
),
|
||||
)
|
||||
)
|
||||
else:
|
||||
moy_ues.append((ue["acronyme"], ""))
|
||||
rg_ues = [
|
||||
("rang_" + ue["acronyme"], nt.ue_rangs[ue["ue_id"]][0][etudid])
|
||||
for ue in ues
|
||||
]
|
||||
|
||||
# Moyennes et rang des modules
|
||||
modimpls = nt.get_modimpls_dict() # recupération des modules
|
||||
modules = []
|
||||
rangs = []
|
||||
for ue in ues: # on parcourt chaque UE
|
||||
for modimpl in modimpls: # dans chaque UE les modules
|
||||
if modimpl["module"]["ue_id"] == ue["ue_id"]:
|
||||
codeModule = modimpl["module"]["code"] or ""
|
||||
noteModule = scu.fmt_note(
|
||||
nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)
|
||||
)
|
||||
if noteModule != "NI": # si étudiant inscrit au module
|
||||
if nt.mod_rangs is not None:
|
||||
rangModule = nt.mod_rangs[modimpl["moduleimpl_id"]][
|
||||
0
|
||||
][etudid]
|
||||
else:
|
||||
rangModule = ""
|
||||
modules.append([codeModule, noteModule])
|
||||
rangs.append(["rang_" + codeModule, rangModule])
|
||||
|
||||
# Absences
|
||||
nbabs, nbabsjust = sco_abs.get_abs_count(etudid, nt.sem)
|
||||
if (
|
||||
dec
|
||||
and not sem_descr # not sem_descr pour ne prendre que le semestre validé le plus récent
|
||||
and (
|
||||
code_semestre_validant(dec["code"])
|
||||
or code_semestre_attente(dec["code"])
|
||||
)
|
||||
and nt.get_etud_etat(etudid) == scu.INSCRIT
|
||||
):
|
||||
d = [
|
||||
("moy", scu.fmt_note(nt.get_etud_moy_gen(etudid))),
|
||||
("moy_promo", scu.fmt_note(nt.moy_moy)),
|
||||
("rang", nt.get_etud_rang(etudid)),
|
||||
("effectif", len(nt.T)),
|
||||
("date_debut", s["date_debut"]),
|
||||
("date_fin", s["date_fin"]),
|
||||
("periode", "%s - %s" % (s["mois_debut"], s["mois_fin"])),
|
||||
("AbsNonJust", nbabs - nbabsjust),
|
||||
("AbsJust", nbabsjust),
|
||||
]
|
||||
d += (
|
||||
moy_ues + rg_ues + modules + rangs
|
||||
) # ajout des 2 champs notes des modules et classement dans chaque module
|
||||
sem_descr = collections.OrderedDict(d)
|
||||
if not sem_descr:
|
||||
sem_descr = collections.OrderedDict(
|
||||
[
|
||||
("moy", ""),
|
||||
("moy_promo", ""),
|
||||
("rang", ""),
|
||||
("effectif", ""),
|
||||
("date_debut", ""),
|
||||
("date_fin", ""),
|
||||
("periode", ""),
|
||||
]
|
||||
)
|
||||
sem_descr["semestre_id"] = sem_id
|
||||
semlist.append(sem_descr)
|
||||
|
||||
I["semlist"] = semlist
|
||||
return I
|
||||
|
||||
|
||||
def _flatten_info(info):
|
||||
# met la liste des infos semestres "a plat"
|
||||
# S1_moy, S1_rang, ..., S2_moy, ...
|
||||
ids = []
|
||||
for s in info["semlist"]:
|
||||
for k, v in s.items():
|
||||
if k != "semestre_id":
|
||||
label = "S%s_%s" % (s["semestre_id"], k)
|
||||
info[label] = v
|
||||
ids.append(label)
|
||||
return ids
|
||||
|
||||
|
||||
def _getEtudInfoGroupes(group_ids, etat=None):
|
||||
"""liste triée d'infos (dict) sur les etudiants du groupe indiqué.
|
||||
Attention: lent, car plusieurs requetes SQL par etudiant !
|
||||
"""
|
||||
etuds = []
|
||||
for group_id in group_ids:
|
||||
members = sco_groups.get_group_members(group_id, etat=etat)
|
||||
for m in members:
|
||||
etud = sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0]
|
||||
etuds.append(etud)
|
||||
|
||||
return etuds
|
||||
|
||||
|
||||
def formsemestre_poursuite_report(formsemestre_id, format="html"):
|
||||
"""Table avec informations "poursuite" """
|
||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||
etuds = _getEtudInfoGroupes([sco_groups.get_default_group(formsemestre_id)])
|
||||
|
||||
infos = []
|
||||
ids = []
|
||||
for etud in etuds:
|
||||
fiche_url = url_for(
|
||||
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etud["etudid"]
|
||||
)
|
||||
etud["_nom_target"] = fiche_url
|
||||
etud["_prenom_target"] = fiche_url
|
||||
etud["_nom_td_attrs"] = 'id="%s" class="etudinfo"' % (etud["etudid"])
|
||||
info = etud_get_poursuite_info(sem, etud)
|
||||
idd = _flatten_info(info)
|
||||
# On recupere la totalite des UEs dans ids
|
||||
for id in idd:
|
||||
if id not in ids:
|
||||
ids += [id]
|
||||
infos.append(info)
|
||||
#
|
||||
column_ids = (
|
||||
("civilite_str", "nom", "prenom", "annee", "date_naissance")
|
||||
+ tuple(ids)
|
||||
+ ("debouche",)
|
||||
)
|
||||
titles = {}
|
||||
for c in column_ids:
|
||||
titles[c] = c
|
||||
tab = GenTable(
|
||||
titles=titles,
|
||||
columns_ids=column_ids,
|
||||
rows=infos,
|
||||
# html_col_width='4em',
|
||||
html_sortable=True,
|
||||
html_class="table_leftalign table_listegroupe",
|
||||
pdf_link=False, # pas d'export pdf
|
||||
preferences=sco_preferences.SemPreferences(formsemestre_id),
|
||||
)
|
||||
tab.filename = scu.make_filename("poursuite " + sem["titreannee"])
|
||||
|
||||
tab.origin = (
|
||||
"Généré par %s le " % sco_version.SCONAME + scu.timedate_human_repr() + ""
|
||||
)
|
||||
tab.caption = "Récapitulatif %s." % sem["titreannee"]
|
||||
tab.html_caption = "Récapitulatif %s." % sem["titreannee"]
|
||||
tab.base_url = "%s?formsemestre_id=%s" % (request.base_url, formsemestre_id)
|
||||
return tab.make_page(
|
||||
title="""<h2 class="formsemestre">Poursuite d'études</h2>""",
|
||||
init_qtip=True,
|
||||
javascripts=["js/etud_info.js"],
|
||||
format=format,
|
||||
with_html_headers=True,
|
||||
)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,478 +1,480 @@
|
|||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""Photos: trombinoscopes - Version IUT Tours
|
||||
Code contribué par Jérôme Billoue, IUT de Tours, 2014
|
||||
Modification Jérome Billoue,Vincent Grimaud, IUT de Tours, 2017
|
||||
"""
|
||||
|
||||
import io
|
||||
|
||||
from reportlab.lib import colors
|
||||
from reportlab.lib.colors import black
|
||||
from reportlab.lib.pagesizes import A4, A3
|
||||
from reportlab.lib import styles
|
||||
from reportlab.lib.pagesizes import landscape
|
||||
from reportlab.lib.units import cm
|
||||
from reportlab.platypus import KeepInFrame, Paragraph, Table, TableStyle
|
||||
from reportlab.platypus.doctemplate import BaseDocTemplate
|
||||
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc.sco_exceptions import ScoPDFFormatError
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_groups_view
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_trombino
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_pdf import SU, ScoDocPageTemplate
|
||||
|
||||
# Paramétrage de l'aspect graphique:
|
||||
PHOTOWIDTH = 2.8 * cm
|
||||
COLWIDTH = 3.4 * cm
|
||||
N_PER_ROW = 5
|
||||
|
||||
|
||||
def pdf_trombino_tours(
|
||||
group_ids=(), # liste des groupes à afficher
|
||||
formsemestre_id=None, # utilisé si pas de groupes selectionné
|
||||
):
|
||||
"""Generation du trombinoscope en fichier PDF"""
|
||||
# Informations sur les groupes à afficher:
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
group_ids, formsemestre_id=formsemestre_id
|
||||
)
|
||||
|
||||
DeptName = sco_preferences.get_preference("DeptName")
|
||||
DeptFullName = sco_preferences.get_preference("DeptFullName")
|
||||
InstituteName = sco_preferences.get_preference("InstituteName")
|
||||
# Generate PDF page
|
||||
StyleSheet = styles.getSampleStyleSheet()
|
||||
objects = []
|
||||
T = Table(
|
||||
[
|
||||
[Paragraph(SU(InstituteName), StyleSheet["Heading3"])],
|
||||
[
|
||||
Paragraph(
|
||||
SU("Département " + DeptFullName or "(?)"), StyleSheet["Heading3"]
|
||||
)
|
||||
],
|
||||
[
|
||||
Paragraph(
|
||||
SU("Date ............ / ............ / ......................"),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
Paragraph(
|
||||
SU(
|
||||
"Module ......................................................."
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
],
|
||||
[
|
||||
Paragraph(
|
||||
SU("de ............h............ à ............h............ "),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
Paragraph(
|
||||
SU("Enseignant ................................................."),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
],
|
||||
[
|
||||
Table(
|
||||
[
|
||||
[
|
||||
"Séance notée :",
|
||||
" ",
|
||||
"DS ",
|
||||
" ",
|
||||
"TP Contrôle ",
|
||||
" ",
|
||||
"Autre cas (TD ou TP noté, QCM, etc...)",
|
||||
]
|
||||
],
|
||||
style=TableStyle(
|
||||
[
|
||||
("ALIGN", (0, 0), (-1, -1), "LEFT"),
|
||||
("BOX", (1, 0), (1, 0), 0.75, black),
|
||||
("BOX", (3, 0), (3, 0), 0.75, black),
|
||||
("BOX", (5, 0), (5, 0), 0.75, black),
|
||||
]
|
||||
),
|
||||
)
|
||||
],
|
||||
],
|
||||
colWidths=(COLWIDTH * N_PER_ROW) / 2,
|
||||
style=TableStyle(
|
||||
[
|
||||
("ALIGN", (0, 0), (-1, -1), "LEFT"),
|
||||
("SPAN", (0, 1), (1, 1)),
|
||||
("SPAN", (0, 4), (1, 4)),
|
||||
("BOTTOMPADDING", (0, -1), (-1, -1), 10),
|
||||
("BOX", (0, 0), (-1, -1), 0.75, black),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
objects.append(T)
|
||||
|
||||
groups = ""
|
||||
|
||||
for group_id in groups_infos.group_ids:
|
||||
if group_id != "None":
|
||||
members, _, group_tit, sem, _ = sco_groups.get_group_infos(group_id, "I")
|
||||
groups += " %s" % group_tit
|
||||
L = []
|
||||
currow = []
|
||||
|
||||
if sem["semestre_id"] != -1:
|
||||
currow = [
|
||||
Paragraph(
|
||||
SU(
|
||||
"<para align=center>Semestre %s</para>" % sem["semestre_id"]
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
]
|
||||
currow += [" "] * (N_PER_ROW - len(currow) - 1)
|
||||
currow += [
|
||||
Paragraph(
|
||||
SU("<para align=center>%s</para>" % sem["anneescolaire"]),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
]
|
||||
L.append(currow)
|
||||
currow = [" "] * N_PER_ROW
|
||||
L.append(currow)
|
||||
|
||||
currow = []
|
||||
currow.append(
|
||||
Paragraph(
|
||||
SU("<para align=center><b>" + group_tit + "</b></para>"),
|
||||
StyleSheet["Heading3"],
|
||||
)
|
||||
)
|
||||
n = 1
|
||||
for m in members:
|
||||
img = sco_trombino._get_etud_platypus_image(m, image_width=PHOTOWIDTH)
|
||||
etud_main_group = sco_groups.get_etud_main_group(
|
||||
m["etudid"], sem["formsemestre_id"]
|
||||
)
|
||||
if group_id != etud_main_group["group_id"]:
|
||||
text_group = " (" + etud_main_group["group_name"] + ")"
|
||||
else:
|
||||
text_group = ""
|
||||
elem = Table(
|
||||
[
|
||||
[img],
|
||||
[
|
||||
Paragraph(
|
||||
SU(
|
||||
"<para align=center><font size=8>"
|
||||
+ sco_etud.format_prenom(m["prenom"])
|
||||
+ " "
|
||||
+ sco_etud.format_nom(m["nom"])
|
||||
+ text_group
|
||||
+ "</font></para>"
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
],
|
||||
],
|
||||
colWidths=[COLWIDTH],
|
||||
style=TableStyle([("ALIGN", (0, 0), (-1, -1), "CENTER")]),
|
||||
)
|
||||
currow.append(elem)
|
||||
if n == (N_PER_ROW - 1):
|
||||
L.append(currow)
|
||||
currow = []
|
||||
n = (n + 1) % N_PER_ROW
|
||||
if currow:
|
||||
currow += [" "] * (N_PER_ROW - len(currow))
|
||||
L.append(currow)
|
||||
if not L:
|
||||
T = Paragraph(SU("Aucune photo à exporter !"), StyleSheet["Normal"])
|
||||
else:
|
||||
T = Table(
|
||||
L,
|
||||
colWidths=[COLWIDTH] * N_PER_ROW,
|
||||
style=TableStyle(
|
||||
[
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 0),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 0),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 0),
|
||||
("TOPPADDING", (0, 1), (-1, -1), 0),
|
||||
("TOPPADDING", (0, 0), (-1, 0), 10),
|
||||
("LINEBELOW", (1, 0), (-2, 0), 0.75, black),
|
||||
("VALIGN", (0, 0), (-1, 1), "MIDDLE"),
|
||||
("VALIGN", (0, 2), (-1, -1), "TOP"),
|
||||
("VALIGN", (0, 2), (0, 2), "MIDDLE"),
|
||||
("SPAN", (0, 0), (0, 1)),
|
||||
("SPAN", (-1, 0), (-1, 1)),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
objects.append(T)
|
||||
|
||||
T = Table(
|
||||
[
|
||||
[
|
||||
Paragraph(
|
||||
SU(
|
||||
"Nombre d'absents : ................. (Merci d'entourer les absents SVP)"
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
]
|
||||
],
|
||||
colWidths=(COLWIDTH * N_PER_ROW),
|
||||
style=TableStyle(
|
||||
[
|
||||
("ALIGN", (0, 0), (-1, -1), "CENTER"),
|
||||
("BOTTOMPADDING", (0, -1), (-1, -1), 10),
|
||||
("BOX", (0, 0), (-1, -1), 0.75, black),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
objects.append(T)
|
||||
|
||||
# Réduit sur une page
|
||||
objects = [KeepInFrame(0, 0, objects, mode="shrink")]
|
||||
# Build document
|
||||
report = io.BytesIO() # in-memory document, no disk file
|
||||
filename = "trombino-%s-%s.pdf" % (DeptName, groups_infos.groups_filename)
|
||||
document = BaseDocTemplate(report)
|
||||
document.addPageTemplates(
|
||||
ScoDocPageTemplate(
|
||||
document,
|
||||
preferences=sco_preferences.SemPreferences(),
|
||||
)
|
||||
)
|
||||
try:
|
||||
document.build(objects)
|
||||
except (ValueError, KeyError) as exc:
|
||||
raise ScoPDFFormatError(str(exc)) from exc
|
||||
data = report.getvalue()
|
||||
|
||||
return scu.sendPDFFile(data, filename)
|
||||
|
||||
|
||||
# Feuille d'absences en pdf avec photos:
|
||||
|
||||
|
||||
def pdf_feuille_releve_absences(
|
||||
group_ids=(), # liste des groupes à afficher
|
||||
formsemestre_id=None, # utilisé si pas de groupes selectionné
|
||||
):
|
||||
"""Generation de la feuille d'absence en fichier PDF, avec photos"""
|
||||
|
||||
NB_CELL_AM = sco_preferences.get_preference("feuille_releve_abs_AM")
|
||||
NB_CELL_PM = sco_preferences.get_preference("feuille_releve_abs_PM")
|
||||
col_width = 0.85 * cm
|
||||
if sco_preferences.get_preference("feuille_releve_abs_samedi"):
|
||||
days = sco_abs.DAYNAMES[:6] # Lundi, ..., Samedi
|
||||
else:
|
||||
days = sco_abs.DAYNAMES[:5] # Lundi, ..., Vendredi
|
||||
nb_days = len(days)
|
||||
|
||||
# Informations sur les groupes à afficher:
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
group_ids, formsemestre_id=formsemestre_id
|
||||
)
|
||||
|
||||
DeptName = sco_preferences.get_preference("DeptName")
|
||||
DeptFullName = sco_preferences.get_preference("DeptFullName")
|
||||
InstituteName = sco_preferences.get_preference("InstituteName")
|
||||
# Generate PDF page
|
||||
StyleSheet = styles.getSampleStyleSheet()
|
||||
objects = [
|
||||
Table(
|
||||
[
|
||||
[
|
||||
Paragraph(SU(InstituteName), StyleSheet["Heading3"]),
|
||||
Paragraph(
|
||||
SU(
|
||||
"<para align=right>Semaine ..................................................................</para>"
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
],
|
||||
[
|
||||
Paragraph(
|
||||
SU("Département " + (DeptFullName or "(?)")),
|
||||
StyleSheet["Heading3"],
|
||||
),
|
||||
"",
|
||||
],
|
||||
],
|
||||
style=TableStyle(
|
||||
[("SPAN", (0, 1), (1, 1)), ("BOTTOMPADDING", (0, -1), (-1, -1), 10)]
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
currow = [""] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)
|
||||
elem_day = Table(
|
||||
[currow],
|
||||
colWidths=([col_width] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)),
|
||||
style=TableStyle(
|
||||
[
|
||||
("GRID", (0, 0), (NB_CELL_AM - 1, 0), 0.25, black),
|
||||
(
|
||||
"GRID",
|
||||
(NB_CELL_AM + 1, 0),
|
||||
(NB_CELL_AM + NB_CELL_PM, 0),
|
||||
0.25,
|
||||
black,
|
||||
),
|
||||
]
|
||||
),
|
||||
)
|
||||
W = []
|
||||
currow = []
|
||||
for n in range(nb_days):
|
||||
currow.append(elem_day)
|
||||
W.append(currow)
|
||||
|
||||
elem_week = Table(
|
||||
W,
|
||||
colWidths=([col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
|
||||
style=TableStyle(
|
||||
[
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 0),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 0),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 0),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 0),
|
||||
]
|
||||
),
|
||||
)
|
||||
currow = []
|
||||
for n in range(nb_days):
|
||||
currow += [Paragraph(SU("<b>" + days[n] + "</b>"), StyleSheet["Normal"])]
|
||||
|
||||
elem_day_name = Table(
|
||||
[currow],
|
||||
colWidths=([col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
|
||||
style=TableStyle(
|
||||
[
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 0),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 0),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 0),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 0),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
for group_id in groups_infos.group_ids:
|
||||
members, _, group_tit, _, _ = sco_groups.get_group_infos(group_id, "I")
|
||||
L = []
|
||||
|
||||
currow = [
|
||||
Paragraph(SU("<b>Groupe " + group_tit + "</b>"), StyleSheet["Normal"])
|
||||
]
|
||||
currow.append(elem_day_name)
|
||||
L.append(currow)
|
||||
|
||||
currow = [Paragraph(SU("Initiales enseignant :"), StyleSheet["Normal"])]
|
||||
currow.append(elem_week)
|
||||
L.append(currow)
|
||||
|
||||
currow = [Paragraph(SU("Initiales module :"), StyleSheet["Normal"])]
|
||||
currow.append(elem_week)
|
||||
L.append(currow)
|
||||
|
||||
for m in members:
|
||||
currow = [
|
||||
Paragraph(
|
||||
SU(
|
||||
sco_etud.format_nom(m["nom"])
|
||||
+ " "
|
||||
+ sco_etud.format_prenom(m["prenom"])
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
]
|
||||
currow.append(elem_week)
|
||||
L.append(currow)
|
||||
|
||||
if not L:
|
||||
T = Paragraph(SU("Aucun étudiant !"), StyleSheet["Normal"])
|
||||
else:
|
||||
T = Table(
|
||||
L,
|
||||
colWidths=(
|
||||
[
|
||||
5.0 * cm,
|
||||
(col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1) * nb_days),
|
||||
]
|
||||
),
|
||||
style=TableStyle(
|
||||
[
|
||||
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 0),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 0),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 3),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 3),
|
||||
("BOTTOMPADDING", (0, -1), (-1, -1), 10),
|
||||
(
|
||||
"ROWBACKGROUNDS",
|
||||
(0, 2),
|
||||
(-1, -1),
|
||||
(colors.white, colors.lightgrey),
|
||||
),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
objects.append(T)
|
||||
|
||||
# Réduit sur une page
|
||||
objects = [KeepInFrame(0, 0, objects, mode="shrink")]
|
||||
# Build document
|
||||
report = io.BytesIO() # in-memory document, no disk file
|
||||
filename = "absences-%s-%s.pdf" % (DeptName, groups_infos.groups_filename)
|
||||
if sco_preferences.get_preference("feuille_releve_abs_taille") == "A3":
|
||||
taille = A3
|
||||
elif sco_preferences.get_preference("feuille_releve_abs_taille") == "A4":
|
||||
taille = A4
|
||||
if sco_preferences.get_preference("feuille_releve_abs_format") == "Paysage":
|
||||
document = BaseDocTemplate(report, pagesize=landscape(taille))
|
||||
else:
|
||||
document = BaseDocTemplate(report, pagesize=taille)
|
||||
document.addPageTemplates(
|
||||
ScoDocPageTemplate(
|
||||
document,
|
||||
preferences=sco_preferences.SemPreferences(),
|
||||
)
|
||||
)
|
||||
document.build(objects)
|
||||
data = report.getvalue()
|
||||
|
||||
return scu.sendPDFFile(data, filename)
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gestion scolarite IUT
|
||||
#
|
||||
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""Photos: trombinoscopes - Version IUT Tours
|
||||
Code contribué par Jérôme Billoue, IUT de Tours, 2014
|
||||
Modification Jérome Billoue,Vincent Grimaud, IUT de Tours, 2017
|
||||
"""
|
||||
|
||||
import io
|
||||
|
||||
from reportlab.lib import colors
|
||||
from reportlab.lib.colors import black
|
||||
from reportlab.lib.pagesizes import A4, A3
|
||||
from reportlab.lib import styles
|
||||
from reportlab.lib.pagesizes import landscape
|
||||
from reportlab.lib.units import cm
|
||||
from reportlab.platypus import KeepInFrame, Paragraph, Table, TableStyle
|
||||
from reportlab.platypus.doctemplate import BaseDocTemplate
|
||||
|
||||
from app.scodoc import sco_abs
|
||||
from app.scodoc import sco_etud
|
||||
from app.scodoc.sco_exceptions import ScoPDFFormatError
|
||||
from app.scodoc import sco_groups
|
||||
from app.scodoc import sco_groups_view
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_trombino
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.sco_pdf import SU, ScoDocPageTemplate
|
||||
|
||||
# Paramétrage de l'aspect graphique:
|
||||
PHOTOWIDTH = 2.8 * cm
|
||||
COLWIDTH = 3.4 * cm
|
||||
N_PER_ROW = 5
|
||||
|
||||
|
||||
def pdf_trombino_tours(
|
||||
group_ids=(), # liste des groupes à afficher
|
||||
formsemestre_id=None, # utilisé si pas de groupes selectionné
|
||||
):
|
||||
"""Generation du trombinoscope en fichier PDF"""
|
||||
# Informations sur les groupes à afficher:
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
group_ids, formsemestre_id=formsemestre_id
|
||||
)
|
||||
|
||||
DeptName = sco_preferences.get_preference("DeptName")
|
||||
DeptFullName = sco_preferences.get_preference("DeptFullName")
|
||||
InstituteName = sco_preferences.get_preference("InstituteName")
|
||||
# Generate PDF page
|
||||
StyleSheet = styles.getSampleStyleSheet()
|
||||
objects = []
|
||||
T = Table(
|
||||
[
|
||||
[Paragraph(SU(InstituteName), StyleSheet["Heading3"])],
|
||||
[
|
||||
Paragraph(
|
||||
SU("Département " + DeptFullName or "(?)"), StyleSheet["Heading3"]
|
||||
)
|
||||
],
|
||||
[
|
||||
Paragraph(
|
||||
SU("Date ............ / ............ / ......................"),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
Paragraph(
|
||||
SU(
|
||||
"Module ......................................................."
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
],
|
||||
[
|
||||
Paragraph(
|
||||
SU("de ............h............ à ............h............ "),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
Paragraph(
|
||||
SU("Enseignant ................................................."),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
],
|
||||
[
|
||||
Table(
|
||||
[
|
||||
[
|
||||
"Séance notée :",
|
||||
" ",
|
||||
"DS ",
|
||||
" ",
|
||||
"TP Contrôle ",
|
||||
" ",
|
||||
"Autre cas (TD ou TP noté, QCM, etc...)",
|
||||
]
|
||||
],
|
||||
style=TableStyle(
|
||||
[
|
||||
("ALIGN", (0, 0), (-1, -1), "LEFT"),
|
||||
("BOX", (1, 0), (1, 0), 0.75, black),
|
||||
("BOX", (3, 0), (3, 0), 0.75, black),
|
||||
("BOX", (5, 0), (5, 0), 0.75, black),
|
||||
]
|
||||
),
|
||||
)
|
||||
],
|
||||
],
|
||||
colWidths=(COLWIDTH * N_PER_ROW) / 2,
|
||||
style=TableStyle(
|
||||
[
|
||||
("ALIGN", (0, 0), (-1, -1), "LEFT"),
|
||||
("SPAN", (0, 1), (1, 1)),
|
||||
("SPAN", (0, 4), (1, 4)),
|
||||
("BOTTOMPADDING", (0, -1), (-1, -1), 10),
|
||||
("BOX", (0, 0), (-1, -1), 0.75, black),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
objects.append(T)
|
||||
|
||||
groups = ""
|
||||
|
||||
for group_id in groups_infos.group_ids:
|
||||
if group_id != "None":
|
||||
members, _, group_tit, sem, _ = sco_groups.get_group_infos(
|
||||
group_id, scu.INSCRIT
|
||||
)
|
||||
groups += " %s" % group_tit
|
||||
L = []
|
||||
currow = []
|
||||
|
||||
if sem["semestre_id"] != -1:
|
||||
currow = [
|
||||
Paragraph(
|
||||
SU(
|
||||
"<para align=center>Semestre %s</para>" % sem["semestre_id"]
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
]
|
||||
currow += [" "] * (N_PER_ROW - len(currow) - 1)
|
||||
currow += [
|
||||
Paragraph(
|
||||
SU("<para align=center>%s</para>" % sem["anneescolaire"]),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
]
|
||||
L.append(currow)
|
||||
currow = [" "] * N_PER_ROW
|
||||
L.append(currow)
|
||||
|
||||
currow = []
|
||||
currow.append(
|
||||
Paragraph(
|
||||
SU("<para align=center><b>" + group_tit + "</b></para>"),
|
||||
StyleSheet["Heading3"],
|
||||
)
|
||||
)
|
||||
n = 1
|
||||
for m in members:
|
||||
img = sco_trombino._get_etud_platypus_image(m, image_width=PHOTOWIDTH)
|
||||
etud_main_group = sco_groups.get_etud_main_group(
|
||||
m["etudid"], sem["formsemestre_id"]
|
||||
)
|
||||
if group_id != etud_main_group["group_id"]:
|
||||
text_group = " (" + etud_main_group["group_name"] + ")"
|
||||
else:
|
||||
text_group = ""
|
||||
elem = Table(
|
||||
[
|
||||
[img],
|
||||
[
|
||||
Paragraph(
|
||||
SU(
|
||||
"<para align=center><font size=8>"
|
||||
+ sco_etud.format_prenom(m["prenom"])
|
||||
+ " "
|
||||
+ sco_etud.format_nom(m["nom"])
|
||||
+ text_group
|
||||
+ "</font></para>"
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
],
|
||||
],
|
||||
colWidths=[COLWIDTH],
|
||||
style=TableStyle([("ALIGN", (0, 0), (-1, -1), "CENTER")]),
|
||||
)
|
||||
currow.append(elem)
|
||||
if n == (N_PER_ROW - 1):
|
||||
L.append(currow)
|
||||
currow = []
|
||||
n = (n + 1) % N_PER_ROW
|
||||
if currow:
|
||||
currow += [" "] * (N_PER_ROW - len(currow))
|
||||
L.append(currow)
|
||||
if not L:
|
||||
T = Paragraph(SU("Aucune photo à exporter !"), StyleSheet["Normal"])
|
||||
else:
|
||||
T = Table(
|
||||
L,
|
||||
colWidths=[COLWIDTH] * N_PER_ROW,
|
||||
style=TableStyle(
|
||||
[
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 0),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 0),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 0),
|
||||
("TOPPADDING", (0, 1), (-1, -1), 0),
|
||||
("TOPPADDING", (0, 0), (-1, 0), 10),
|
||||
("LINEBELOW", (1, 0), (-2, 0), 0.75, black),
|
||||
("VALIGN", (0, 0), (-1, 1), "MIDDLE"),
|
||||
("VALIGN", (0, 2), (-1, -1), "TOP"),
|
||||
("VALIGN", (0, 2), (0, 2), "MIDDLE"),
|
||||
("SPAN", (0, 0), (0, 1)),
|
||||
("SPAN", (-1, 0), (-1, 1)),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
objects.append(T)
|
||||
|
||||
T = Table(
|
||||
[
|
||||
[
|
||||
Paragraph(
|
||||
SU(
|
||||
"Nombre d'absents : ................. (Merci d'entourer les absents SVP)"
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
]
|
||||
],
|
||||
colWidths=(COLWIDTH * N_PER_ROW),
|
||||
style=TableStyle(
|
||||
[
|
||||
("ALIGN", (0, 0), (-1, -1), "CENTER"),
|
||||
("BOTTOMPADDING", (0, -1), (-1, -1), 10),
|
||||
("BOX", (0, 0), (-1, -1), 0.75, black),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
objects.append(T)
|
||||
|
||||
# Réduit sur une page
|
||||
objects = [KeepInFrame(0, 0, objects, mode="shrink")]
|
||||
# Build document
|
||||
report = io.BytesIO() # in-memory document, no disk file
|
||||
filename = "trombino-%s-%s.pdf" % (DeptName, groups_infos.groups_filename)
|
||||
document = BaseDocTemplate(report)
|
||||
document.addPageTemplates(
|
||||
ScoDocPageTemplate(
|
||||
document,
|
||||
preferences=sco_preferences.SemPreferences(),
|
||||
)
|
||||
)
|
||||
try:
|
||||
document.build(objects)
|
||||
except (ValueError, KeyError) as exc:
|
||||
raise ScoPDFFormatError(str(exc)) from exc
|
||||
data = report.getvalue()
|
||||
|
||||
return scu.sendPDFFile(data, filename)
|
||||
|
||||
|
||||
# Feuille d'absences en pdf avec photos:
|
||||
|
||||
|
||||
def pdf_feuille_releve_absences(
|
||||
group_ids=(), # liste des groupes à afficher
|
||||
formsemestre_id=None, # utilisé si pas de groupes selectionné
|
||||
):
|
||||
"""Generation de la feuille d'absence en fichier PDF, avec photos"""
|
||||
|
||||
NB_CELL_AM = sco_preferences.get_preference("feuille_releve_abs_AM")
|
||||
NB_CELL_PM = sco_preferences.get_preference("feuille_releve_abs_PM")
|
||||
col_width = 0.85 * cm
|
||||
if sco_preferences.get_preference("feuille_releve_abs_samedi"):
|
||||
days = sco_abs.DAYNAMES[:6] # Lundi, ..., Samedi
|
||||
else:
|
||||
days = sco_abs.DAYNAMES[:5] # Lundi, ..., Vendredi
|
||||
nb_days = len(days)
|
||||
|
||||
# Informations sur les groupes à afficher:
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
group_ids, formsemestre_id=formsemestre_id
|
||||
)
|
||||
|
||||
DeptName = sco_preferences.get_preference("DeptName")
|
||||
DeptFullName = sco_preferences.get_preference("DeptFullName")
|
||||
InstituteName = sco_preferences.get_preference("InstituteName")
|
||||
# Generate PDF page
|
||||
StyleSheet = styles.getSampleStyleSheet()
|
||||
objects = [
|
||||
Table(
|
||||
[
|
||||
[
|
||||
Paragraph(SU(InstituteName), StyleSheet["Heading3"]),
|
||||
Paragraph(
|
||||
SU(
|
||||
"<para align=right>Semaine ..................................................................</para>"
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
),
|
||||
],
|
||||
[
|
||||
Paragraph(
|
||||
SU("Département " + (DeptFullName or "(?)")),
|
||||
StyleSheet["Heading3"],
|
||||
),
|
||||
"",
|
||||
],
|
||||
],
|
||||
style=TableStyle(
|
||||
[("SPAN", (0, 1), (1, 1)), ("BOTTOMPADDING", (0, -1), (-1, -1), 10)]
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
currow = [""] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)
|
||||
elem_day = Table(
|
||||
[currow],
|
||||
colWidths=([col_width] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)),
|
||||
style=TableStyle(
|
||||
[
|
||||
("GRID", (0, 0), (NB_CELL_AM - 1, 0), 0.25, black),
|
||||
(
|
||||
"GRID",
|
||||
(NB_CELL_AM + 1, 0),
|
||||
(NB_CELL_AM + NB_CELL_PM, 0),
|
||||
0.25,
|
||||
black,
|
||||
),
|
||||
]
|
||||
),
|
||||
)
|
||||
W = []
|
||||
currow = []
|
||||
for n in range(nb_days):
|
||||
currow.append(elem_day)
|
||||
W.append(currow)
|
||||
|
||||
elem_week = Table(
|
||||
W,
|
||||
colWidths=([col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
|
||||
style=TableStyle(
|
||||
[
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 0),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 0),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 0),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 0),
|
||||
]
|
||||
),
|
||||
)
|
||||
currow = []
|
||||
for n in range(nb_days):
|
||||
currow += [Paragraph(SU("<b>" + days[n] + "</b>"), StyleSheet["Normal"])]
|
||||
|
||||
elem_day_name = Table(
|
||||
[currow],
|
||||
colWidths=([col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
|
||||
style=TableStyle(
|
||||
[
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 0),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 0),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 0),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 0),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
for group_id in groups_infos.group_ids:
|
||||
members, _, group_tit, _, _ = sco_groups.get_group_infos(group_id, scu.INSCRIT)
|
||||
L = []
|
||||
|
||||
currow = [
|
||||
Paragraph(SU("<b>Groupe " + group_tit + "</b>"), StyleSheet["Normal"])
|
||||
]
|
||||
currow.append(elem_day_name)
|
||||
L.append(currow)
|
||||
|
||||
currow = [Paragraph(SU("Initiales enseignant :"), StyleSheet["Normal"])]
|
||||
currow.append(elem_week)
|
||||
L.append(currow)
|
||||
|
||||
currow = [Paragraph(SU("Initiales module :"), StyleSheet["Normal"])]
|
||||
currow.append(elem_week)
|
||||
L.append(currow)
|
||||
|
||||
for m in members:
|
||||
currow = [
|
||||
Paragraph(
|
||||
SU(
|
||||
sco_etud.format_nom(m["nom"])
|
||||
+ " "
|
||||
+ sco_etud.format_prenom(m["prenom"])
|
||||
),
|
||||
StyleSheet["Normal"],
|
||||
)
|
||||
]
|
||||
currow.append(elem_week)
|
||||
L.append(currow)
|
||||
|
||||
if not L:
|
||||
T = Paragraph(SU("Aucun étudiant !"), StyleSheet["Normal"])
|
||||
else:
|
||||
T = Table(
|
||||
L,
|
||||
colWidths=(
|
||||
[
|
||||
5.0 * cm,
|
||||
(col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1) * nb_days),
|
||||
]
|
||||
),
|
||||
style=TableStyle(
|
||||
[
|
||||
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 0),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 0),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 3),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 3),
|
||||
("BOTTOMPADDING", (0, -1), (-1, -1), 10),
|
||||
(
|
||||
"ROWBACKGROUNDS",
|
||||
(0, 2),
|
||||
(-1, -1),
|
||||
(colors.white, colors.lightgrey),
|
||||
),
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
objects.append(T)
|
||||
|
||||
# Réduit sur une page
|
||||
objects = [KeepInFrame(0, 0, objects, mode="shrink")]
|
||||
# Build document
|
||||
report = io.BytesIO() # in-memory document, no disk file
|
||||
filename = "absences-%s-%s.pdf" % (DeptName, groups_infos.groups_filename)
|
||||
if sco_preferences.get_preference("feuille_releve_abs_taille") == "A3":
|
||||
taille = A3
|
||||
elif sco_preferences.get_preference("feuille_releve_abs_taille") == "A4":
|
||||
taille = A4
|
||||
if sco_preferences.get_preference("feuille_releve_abs_format") == "Paysage":
|
||||
document = BaseDocTemplate(report, pagesize=landscape(taille))
|
||||
else:
|
||||
document = BaseDocTemplate(report, pagesize=taille)
|
||||
document.addPageTemplates(
|
||||
ScoDocPageTemplate(
|
||||
document,
|
||||
preferences=sco_preferences.SemPreferences(),
|
||||
)
|
||||
)
|
||||
document.build(objects)
|
||||
data = report.getvalue()
|
||||
|
||||
return scu.sendPDFFile(data, filename)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
4608
app/views/scolar.py
4608
app/views/scolar.py
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue