diff --git a/app/scodoc/sco_bulletins_pdf.py b/app/scodoc/sco_bulletins_pdf.py index c8887fc5..f3975e84 100644 --- a/app/scodoc/sco_bulletins_pdf.py +++ b/app/scodoc/sco_bulletins_pdf.py @@ -62,10 +62,13 @@ from flask import g, request from app import log, ScoValueError from app.comp.res_but import ResultatsSemestreBUT from app.models import FormSemestre, Identite -from app.scodoc import sco_cache -from app.scodoc import codes_cursus -from app.scodoc import sco_pdf -from app.scodoc import sco_preferences +from app.scodoc import ( + codes_cursus, + sco_cache, + sco_groups_view, + sco_pdf, + sco_preferences, +) from app.scodoc.sco_logos import find_logo 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" from app.but import bulletin_but_court from app.scodoc import sco_bulletins @@ -226,13 +233,20 @@ def get_formsemestre_bulletins_pdf(formsemestre_id, version="selectedevals"): raise ScoValueError( "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: return cached[1], cached[0] fragments = [] # Make each bulletin - - for etud in formsemestre.get_inscrits(include_demdef=True, order=True): + for etud in etuds: if version == "butcourt": frag = bulletin_but_court.bulletin_but_court_pdf_frag(etud, formsemestre) else: diff --git a/app/scodoc/sco_groups_view.py b/app/scodoc/sco_groups_view.py index 0d1d1dfb..ebfffab3 100644 --- a/app/scodoc/sco_groups_view.py +++ b/app/scodoc/sco_groups_view.py @@ -331,6 +331,7 @@ class DisplayedGroupsInfos: empty_list_select_all=True, 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 group_ids: group_ids = [group_ids] # cas ou un seul parametre, pas de liste @@ -466,6 +467,10 @@ class DisplayedGroupsInfos: 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 def groups_table( diff --git a/app/views/notes.py b/app/views/notes.py index 6832b6b4..25170288 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -90,7 +90,6 @@ from app.decorators import ( # --------------- 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 notesdb as ndb from app import log, send_scodoc_alarm from app.scodoc.sco_exceptions import ( @@ -98,59 +97,62 @@ from app.scodoc.sco_exceptions import ( ScoValueError, ScoInvalidIdType, ) -from app.scodoc import html_sco_header -from app.scodoc import sco_apogee_compare -from app.scodoc import sco_archives_formsemestre -from app.scodoc import sco_assiduites -from app.scodoc import sco_bulletins -from app.scodoc import sco_bulletins_pdf -from app.scodoc import sco_cache -from app.scodoc import sco_cost_formation -from app.scodoc import sco_debouche -from app.scodoc import sco_edit_apc -from app.scodoc import sco_edit_formation -from app.scodoc import sco_edit_matiere -from app.scodoc import sco_edit_module -from app.scodoc import sco_edit_ue -from app.scodoc import sco_etape_apogee_view -from app.scodoc import sco_etud -from app.scodoc import sco_evaluations -from app.scodoc import sco_evaluation_check_abs -from app.scodoc import sco_evaluation_db -from app.scodoc import sco_evaluation_edit -from app.scodoc import sco_evaluation_recap -from app.scodoc import sco_export_results -from app.scodoc import sco_formations -from app.scodoc import sco_formation_recap -from app.scodoc import sco_formation_versions -from app.scodoc import sco_formsemestre -from app.scodoc import sco_formsemestre_custommenu -from app.scodoc import sco_formsemestre_edit -from app.scodoc import sco_formsemestre_exterieurs -from app.scodoc import sco_formsemestre_inscriptions -from app.scodoc import sco_formsemestre_status -from app.scodoc import sco_formsemestre_validation -from app.scodoc import sco_inscr_passage -from app.scodoc import sco_liste_notes -from app.scodoc import sco_lycee -from app.scodoc import sco_moduleimpl -from app.scodoc import sco_moduleimpl_inscriptions -from app.scodoc import sco_moduleimpl_status -from app.scodoc import sco_placement -from app.scodoc import sco_poursuite_dut -from app.scodoc import sco_preferences -from app.scodoc import sco_prepajury -from app.scodoc import sco_pv_forms -from app.scodoc import sco_recapcomplet -from app.scodoc import sco_report -from app.scodoc import sco_report_but -from app.scodoc import sco_saisie_notes -from app.scodoc import sco_semset -from app.scodoc import sco_synchro_etuds -from app.scodoc import sco_tag_module -from app.scodoc import sco_ue_external -from app.scodoc import sco_undo_notes -from app.scodoc import sco_users +from app.scodoc import ( + html_sco_header, + sco_apogee_compare, + sco_archives_formsemestre, + sco_assiduites, + sco_bulletins, + sco_bulletins_pdf, + sco_cache, + sco_cost_formation, + sco_debouche, + sco_edit_apc, + sco_edit_formation, + sco_edit_matiere, + sco_edit_module, + sco_edit_ue, + sco_etape_apogee_view, + sco_etud, + sco_evaluations, + sco_evaluation_check_abs, + sco_evaluation_db, + sco_evaluation_edit, + sco_evaluation_recap, + sco_export_results, + sco_formations, + sco_formation_recap, + sco_formation_versions, + sco_formsemestre, + sco_formsemestre_custommenu, + sco_formsemestre_edit, + sco_formsemestre_exterieurs, + sco_formsemestre_inscriptions, + sco_formsemestre_status, + sco_formsemestre_validation, + sco_groups_view, + sco_inscr_passage, + sco_liste_notes, + sco_lycee, + sco_moduleimpl, + sco_moduleimpl_inscriptions, + sco_moduleimpl_status, + sco_placement, + sco_poursuite_dut, + sco_preferences, + sco_prepajury, + sco_pv_forms, + sco_recapcomplet, + sco_report, + sco_report_but, + sco_saisie_notes, + sco_semset, + sco_synchro_etuds, + sco_tag_module, + sco_ue_external, + sco_undo_notes, + sco_users, +) from app.scodoc.gen_tables import GenTable from app.scodoc.sco_pv_dict import descr_autorisations from app.scodoc.sco_permissions import Permission @@ -1844,10 +1846,20 @@ sco_publish( @scodoc @permission_required(Permission.ScoView) @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" + # 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( - formsemestre_id, version=version + formsemestre_id, groups_infos=groups_infos, version=version ) return scu.sendPDFFile(pdfdoc, filename) @@ -1864,18 +1876,29 @@ _EXPL_BULL = """Versions des bulletins: @scodoc @permission_required(Permission.ScoView) @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""" 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: 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 _formsemestre_bulletins_choice( formsemestre, - title="Choisir la version des bulletins à générer", 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, dialog_confirmed=False, prefer_mail_perso=0, + group_ids: list[int] = None, # si indiqué, ne prend que ces groupes ): """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: return flask.redirect( url_for( @@ -1909,8 +1939,9 @@ def formsemestre_bulletins_mailetuds_choice( scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, version=version, - dialog_confirmed=dialog_confirmed, + dialog_confirmed=int(dialog_confirmed), prefer_mail_perso=prefer_mail_perso, + group_ids=groups_infos.group_ids, ) ) formsemestre = FormSemestre.get_formsemestre(formsemestre_id) @@ -1934,45 +1965,41 @@ def formsemestre_bulletins_mailetuds_choice(

""" + expl_bull, choose_mail=True, + groups_infos=groups_infos, ) # not published 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""" - versions = ( + """Choix d'une version de bulletin + (pour envois mail ou génération classeur pdf) + """ + versions_bulletins = ( scu.BULLETINS_VERSIONS_BUT if formsemestre.formation.is_apc() else scu.BULLETINS_VERSIONS ) - H = [ - html_sco_header.html_sem_header(title), - f""" -

- - """, - ] - H.append("""  """) - if choose_mail: - H.append( - """
- Utiliser si possible les adresses personnelles -
""" - ) - - H.append(f"""

{explanation}

""") - - return "\n".join(H) + html_sco_header.sco_footer() + return render_template( + "formsemestre/bulletins_choice.j2", + explanation=explanation, + choose_mail=choose_mail, + formsemestre=formsemestre, + menu_groups_choice=sco_groups_view.menu_groups_choice(groups_infos), + sco=ScoData(formsemestre=formsemestre), + sco_groups_view=sco_groups_view, + title=title, + versions_bulletins=versions_bulletins, + ) -@bp.route("/formsemestre_bulletins_mailetuds") +@bp.route("/formsemestre_bulletins_mailetuds", methods=["GET", "POST"]) @scodoc @permission_required(Permission.ScoView) @scodoc7func @@ -1981,16 +2008,23 @@ def formsemestre_bulletins_mailetuds( version="long", dialog_confirmed=False, prefer_mail_perso=0, + group_ids: list[int] = None, # si indiqué, ne prend que ces groupes ): """Envoie à chaque etudiant son bulletin (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) formsemestre = FormSemestre.get_formsemestre(formsemestre_id) inscriptions = [ inscription 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): @@ -1998,7 +2032,7 @@ def formsemestre_bulletins_mailetuds( # Confirmation dialog if not dialog_confirmed: return scu.confirm_dialog( - f"

Envoyer les {len(inscriptions)} bulletins par e-mail aux étudiants inscrits ?", + f"

Envoyer les {len(inscriptions)} bulletins par e-mail aux étudiants inscrits sélectionnés ?", dest_url="", cancel_url=url_for( "notes.formsemestre_status",