Envoi bulletin, génération classeur: choix groupe étudiants

This commit is contained in:
Emmanuel Viennet 2024-02-22 16:43:00 +01:00
parent f1ce70e6de
commit 13e7bd4512
3 changed files with 149 additions and 96 deletions

View File

@ -62,10 +62,13 @@ from flask import g, request
from app import log, ScoValueError from app import log, ScoValueError
from app.comp.res_but import ResultatsSemestreBUT from app.comp.res_but import ResultatsSemestreBUT
from app.models import FormSemestre, Identite from app.models import FormSemestre, Identite
from app.scodoc import sco_cache from app.scodoc import (
from app.scodoc import codes_cursus codes_cursus,
from app.scodoc import sco_pdf sco_cache,
from app.scodoc import sco_preferences sco_groups_view,
sco_pdf,
sco_preferences,
)
from app.scodoc.sco_logos import find_logo from app.scodoc.sco_logos import find_logo
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
@ -211,7 +214,11 @@ def process_field(
) )
def get_formsemestre_bulletins_pdf(formsemestre_id, version="selectedevals"): def get_formsemestre_bulletins_pdf(
formsemestre_id,
version="selectedevals",
groups_infos=None, # si indiqué, ne prend que ces groupes
):
"Document pdf avec tous les bulletins du semestre, et filename" "Document pdf avec tous les bulletins du semestre, et filename"
from app.but import bulletin_but_court from app.but import bulletin_but_court
from app.scodoc import sco_bulletins from app.scodoc import sco_bulletins
@ -226,13 +233,20 @@ def get_formsemestre_bulletins_pdf(formsemestre_id, version="selectedevals"):
raise ScoValueError( raise ScoValueError(
"get_formsemestre_bulletins_pdf: version de bulletin demandée invalide !" "get_formsemestre_bulletins_pdf: version de bulletin demandée invalide !"
) )
cached = sco_cache.SemBulletinsPDFCache.get(str(formsemestre_id) + "_" + version)
etuds = formsemestre.get_inscrits(include_demdef=True, order=True)
if groups_infos is not None:
etudids = {m["etudid"] for m in groups_infos.members}
etuds = [etud for etud in etuds if etud.id in etudids]
cache_key = (
str(formsemestre_id) + "_" + version + "_" + groups_infos.get_groups_key()
)
cached = sco_cache.SemBulletinsPDFCache.get(cache_key)
if cached: if cached:
return cached[1], cached[0] return cached[1], cached[0]
fragments = [] fragments = []
# Make each bulletin # Make each bulletin
for etud in etuds:
for etud in formsemestre.get_inscrits(include_demdef=True, order=True):
if version == "butcourt": if version == "butcourt":
frag = bulletin_but_court.bulletin_but_court_pdf_frag(etud, formsemestre) frag = bulletin_but_court.bulletin_but_court_pdf_frag(etud, formsemestre)
else: else:

View File

@ -331,6 +331,7 @@ class DisplayedGroupsInfos:
empty_list_select_all=True, empty_list_select_all=True,
moduleimpl_id=None, # used to find formsemestre when unspecified moduleimpl_id=None, # used to find formsemestre when unspecified
): ):
group_ids = [] if group_ids is None else group_ids
if isinstance(group_ids, int): if isinstance(group_ids, int):
if group_ids: if group_ids:
group_ids = [group_ids] # cas ou un seul parametre, pas de liste group_ids = [group_ids] # cas ou un seul parametre, pas de liste
@ -466,6 +467,10 @@ class DisplayedGroupsInfos:
else None else None
) )
def get_groups_key(self) -> str:
"clé identifiant les groupes sélectionnés, utile pour cache"
return "-".join(str(x) for x in sorted(self.group_ids))
# Ancien ZScolar.group_list renommé ici en group_table # Ancien ZScolar.group_list renommé ici en group_table
def groups_table( def groups_table(

View File

@ -90,7 +90,6 @@ from app.decorators import (
# --------------- # ---------------
from app.pe import pe_view # ne pas enlever, ajoute des vues from app.pe import pe_view # ne pas enlever, ajoute des vues
from app.scodoc import sco_bulletins_json, sco_utils as scu from app.scodoc import sco_bulletins_json, sco_utils as scu
from app.scodoc import notesdb as ndb
from app import log, send_scodoc_alarm from app import log, send_scodoc_alarm
from app.scodoc.sco_exceptions import ( from app.scodoc.sco_exceptions import (
@ -98,59 +97,62 @@ from app.scodoc.sco_exceptions import (
ScoValueError, ScoValueError,
ScoInvalidIdType, ScoInvalidIdType,
) )
from app.scodoc import html_sco_header from app.scodoc import (
from app.scodoc import sco_apogee_compare html_sco_header,
from app.scodoc import sco_archives_formsemestre sco_apogee_compare,
from app.scodoc import sco_assiduites sco_archives_formsemestre,
from app.scodoc import sco_bulletins sco_assiduites,
from app.scodoc import sco_bulletins_pdf sco_bulletins,
from app.scodoc import sco_cache sco_bulletins_pdf,
from app.scodoc import sco_cost_formation sco_cache,
from app.scodoc import sco_debouche sco_cost_formation,
from app.scodoc import sco_edit_apc sco_debouche,
from app.scodoc import sco_edit_formation sco_edit_apc,
from app.scodoc import sco_edit_matiere sco_edit_formation,
from app.scodoc import sco_edit_module sco_edit_matiere,
from app.scodoc import sco_edit_ue sco_edit_module,
from app.scodoc import sco_etape_apogee_view sco_edit_ue,
from app.scodoc import sco_etud sco_etape_apogee_view,
from app.scodoc import sco_evaluations sco_etud,
from app.scodoc import sco_evaluation_check_abs sco_evaluations,
from app.scodoc import sco_evaluation_db sco_evaluation_check_abs,
from app.scodoc import sco_evaluation_edit sco_evaluation_db,
from app.scodoc import sco_evaluation_recap sco_evaluation_edit,
from app.scodoc import sco_export_results sco_evaluation_recap,
from app.scodoc import sco_formations sco_export_results,
from app.scodoc import sco_formation_recap sco_formations,
from app.scodoc import sco_formation_versions sco_formation_recap,
from app.scodoc import sco_formsemestre sco_formation_versions,
from app.scodoc import sco_formsemestre_custommenu sco_formsemestre,
from app.scodoc import sco_formsemestre_edit sco_formsemestre_custommenu,
from app.scodoc import sco_formsemestre_exterieurs sco_formsemestre_edit,
from app.scodoc import sco_formsemestre_inscriptions sco_formsemestre_exterieurs,
from app.scodoc import sco_formsemestre_status sco_formsemestre_inscriptions,
from app.scodoc import sco_formsemestre_validation sco_formsemestre_status,
from app.scodoc import sco_inscr_passage sco_formsemestre_validation,
from app.scodoc import sco_liste_notes sco_groups_view,
from app.scodoc import sco_lycee sco_inscr_passage,
from app.scodoc import sco_moduleimpl sco_liste_notes,
from app.scodoc import sco_moduleimpl_inscriptions sco_lycee,
from app.scodoc import sco_moduleimpl_status sco_moduleimpl,
from app.scodoc import sco_placement sco_moduleimpl_inscriptions,
from app.scodoc import sco_poursuite_dut sco_moduleimpl_status,
from app.scodoc import sco_preferences sco_placement,
from app.scodoc import sco_prepajury sco_poursuite_dut,
from app.scodoc import sco_pv_forms sco_preferences,
from app.scodoc import sco_recapcomplet sco_prepajury,
from app.scodoc import sco_report sco_pv_forms,
from app.scodoc import sco_report_but sco_recapcomplet,
from app.scodoc import sco_saisie_notes sco_report,
from app.scodoc import sco_semset sco_report_but,
from app.scodoc import sco_synchro_etuds sco_saisie_notes,
from app.scodoc import sco_tag_module sco_semset,
from app.scodoc import sco_ue_external sco_synchro_etuds,
from app.scodoc import sco_undo_notes sco_tag_module,
from app.scodoc import sco_users sco_ue_external,
sco_undo_notes,
sco_users,
)
from app.scodoc.gen_tables import GenTable from app.scodoc.gen_tables import GenTable
from app.scodoc.sco_pv_dict import descr_autorisations from app.scodoc.sco_pv_dict import descr_autorisations
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
@ -1844,10 +1846,20 @@ sco_publish(
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
@scodoc7func @scodoc7func
def formsemestre_bulletins_pdf(formsemestre_id, version="selectedevals"): def formsemestre_bulletins_pdf(
formsemestre_id,
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
version="selectedevals",
):
"Publie les bulletins dans un classeur PDF" "Publie les bulletins dans un classeur PDF"
# Informations sur les groupes à utiliser:
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre_id,
select_all_when_unspecified=True,
)
pdfdoc, filename = sco_bulletins_pdf.get_formsemestre_bulletins_pdf( pdfdoc, filename = sco_bulletins_pdf.get_formsemestre_bulletins_pdf(
formsemestre_id, version=version formsemestre_id, groups_infos=groups_infos, version=version
) )
return scu.sendPDFFile(pdfdoc, filename) return scu.sendPDFFile(pdfdoc, filename)
@ -1864,18 +1876,29 @@ _EXPL_BULL = """Versions des bulletins:
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
@scodoc7func @scodoc7func
def formsemestre_bulletins_pdf_choice(formsemestre_id, version=None): def formsemestre_bulletins_pdf_choice(
formsemestre_id,
version=None,
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
):
"""Choix version puis envoi classeur bulletins pdf""" """Choix version puis envoi classeur bulletins pdf"""
formsemestre = FormSemestre.get_formsemestre(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
# Informations sur les groupes à utiliser:
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre_id,
select_all_when_unspecified=True,
)
if version: if version:
pdfdoc, filename = sco_bulletins_pdf.get_formsemestre_bulletins_pdf( pdfdoc, filename = sco_bulletins_pdf.get_formsemestre_bulletins_pdf(
formsemestre_id, version=version formsemestre_id, groups_infos=groups_infos, version=version
) )
return scu.sendPDFFile(pdfdoc, filename) return scu.sendPDFFile(pdfdoc, filename)
return _formsemestre_bulletins_choice( return _formsemestre_bulletins_choice(
formsemestre, formsemestre,
title="Choisir la version des bulletins à générer",
explanation=_EXPL_BULL, explanation=_EXPL_BULL,
groups_infos=groups_infos,
title="Choisir la version des bulletins à générer",
) )
@ -1900,8 +1923,15 @@ def formsemestre_bulletins_mailetuds_choice(
version=None, version=None,
dialog_confirmed=False, dialog_confirmed=False,
prefer_mail_perso=0, prefer_mail_perso=0,
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
): ):
"""Choix version puis envoi classeur bulletins pdf""" """Choix version puis envoi classeur bulletins pdf"""
# Informations sur les groupes à utiliser:
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre_id,
select_all_when_unspecified=True,
)
if version: if version:
return flask.redirect( return flask.redirect(
url_for( url_for(
@ -1909,8 +1939,9 @@ def formsemestre_bulletins_mailetuds_choice(
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
formsemestre_id=formsemestre_id, formsemestre_id=formsemestre_id,
version=version, version=version,
dialog_confirmed=dialog_confirmed, dialog_confirmed=int(dialog_confirmed),
prefer_mail_perso=prefer_mail_perso, prefer_mail_perso=prefer_mail_perso,
group_ids=groups_infos.group_ids,
) )
) )
formsemestre = FormSemestre.get_formsemestre(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
@ -1934,45 +1965,41 @@ def formsemestre_bulletins_mailetuds_choice(
</p><p>""" </p><p>"""
+ expl_bull, + expl_bull,
choose_mail=True, choose_mail=True,
groups_infos=groups_infos,
) )
# not published # not published
def _formsemestre_bulletins_choice( def _formsemestre_bulletins_choice(
formsemestre: FormSemestre, title="", explanation="", choose_mail=False formsemestre: FormSemestre,
title="",
explanation="",
choose_mail=False,
groups_infos=None,
): ):
"""Choix d'une version de bulletin""" """Choix d'une version de bulletin
versions = ( (pour envois mail ou génération classeur pdf)
"""
versions_bulletins = (
scu.BULLETINS_VERSIONS_BUT scu.BULLETINS_VERSIONS_BUT
if formsemestre.formation.is_apc() if formsemestre.formation.is_apc()
else scu.BULLETINS_VERSIONS else scu.BULLETINS_VERSIONS
) )
H = [
html_sco_header.html_sem_header(title),
f"""
<form name="f" method="GET" action="{request.base_url}">
<input type="hidden" name="formsemestre_id" value="{formsemestre.id}"></input>
""",
]
H.append("""<select name="version" class="noprint">""")
for version, description in versions.items():
H.append(f"""<option value="{version}">{description}</option>""")
H.append("""</select>&nbsp;&nbsp;<input type="submit" value="Générer"/>""") return render_template(
if choose_mail: "formsemestre/bulletins_choice.j2",
H.append( explanation=explanation,
"""<div> choose_mail=choose_mail,
<input type="checkbox" name="prefer_mail_perso" value="1" formsemestre=formsemestre,
/>Utiliser si possible les adresses personnelles menu_groups_choice=sco_groups_view.menu_groups_choice(groups_infos),
</div>""" sco=ScoData(formsemestre=formsemestre),
sco_groups_view=sco_groups_view,
title=title,
versions_bulletins=versions_bulletins,
) )
H.append(f"""<p class="help">{explanation}</p>""")
return "\n".join(H) + html_sco_header.sco_footer() @bp.route("/formsemestre_bulletins_mailetuds", methods=["GET", "POST"])
@bp.route("/formsemestre_bulletins_mailetuds")
@scodoc @scodoc
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
@scodoc7func @scodoc7func
@ -1981,16 +2008,23 @@ def formsemestre_bulletins_mailetuds(
version="long", version="long",
dialog_confirmed=False, dialog_confirmed=False,
prefer_mail_perso=0, prefer_mail_perso=0,
group_ids: list[int] = None, # si indiqué, ne prend que ces groupes
): ):
"""Envoie à chaque etudiant son bulletin """Envoie à chaque etudiant son bulletin
(inscrit non démissionnaire ni défaillant et ayant un mail renseigné dans ScoDoc) (inscrit non démissionnaire ni défaillant et ayant un mail renseigné dans ScoDoc)
""" """
groups_infos = sco_groups_view.DisplayedGroupsInfos(
group_ids,
formsemestre_id=formsemestre_id,
select_all_when_unspecified=True,
)
etudids = {m["etudid"] for m in groups_infos.members}
prefer_mail_perso = int(prefer_mail_perso) prefer_mail_perso = int(prefer_mail_perso)
formsemestre = FormSemestre.get_formsemestre(formsemestre_id) formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
inscriptions = [ inscriptions = [
inscription inscription
for inscription in formsemestre.inscriptions for inscription in formsemestre.inscriptions
if inscription.etat == scu.INSCRIT if inscription.etat == scu.INSCRIT and inscription.etudid in etudids
] ]
# #
if not sco_bulletins.can_send_bulletin_by_mail(formsemestre_id): if not sco_bulletins.can_send_bulletin_by_mail(formsemestre_id):
@ -1998,7 +2032,7 @@ def formsemestre_bulletins_mailetuds(
# Confirmation dialog # Confirmation dialog
if not dialog_confirmed: if not dialog_confirmed:
return scu.confirm_dialog( return scu.confirm_dialog(
f"<h2>Envoyer les {len(inscriptions)} bulletins par e-mail aux étudiants inscrits ?", f"<h2>Envoyer les {len(inscriptions)} bulletins par e-mail aux étudiants inscrits sélectionnés ?",
dest_url="", dest_url="",
cancel_url=url_for( cancel_url=url_for(
"notes.formsemestre_status", "notes.formsemestre_status",