############################################################################## # ScoDoc # Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved. # See LICENSE ############################################################################## """Jury BUT: table synthèse résultats semestre / PV """ from flask import g, request, url_for from openpyxl.styles import Font, Border, Side, Alignment, PatternFill from app import log from app.but import jury_but from app.but.cursus_but import but_ects_valides from app.models.etudiants import Identite from app.models.formsemestre import FormSemestre from app.scodoc.gen_tables import GenTable from app.scodoc import sco_excel from app.scodoc.sco_exceptions import ScoValueError from app.scodoc import sco_preferences from app.scodoc import sco_utils as scu def _descr_cursus_but(etud: Identite) -> str: "description de la liste des semestres BUT suivis" # prend simplement tous les semestre de type APC, ce qui sera faux si # l'étudiant change de spécialité au sein du même département # (ce qui ne peut normalement pas se produire) inscriptions = sorted( [ ins for ins in etud.formsemestre_inscriptions if ins.formsemestre.formation.is_apc() ], key=lambda i: i.formsemestre.date_debut, ) indices = [ ins.formsemestre.semestre_id if ins.formsemestre.semestre_id is not None else -1 for ins in inscriptions ] return ", ".join(f"S{indice}" for indice in indices) def pvjury_page_but(formsemestre_id: int, fmt="html"): """Page récapitulant les décisions de jury BUT formsemestre peut être pair ou impair """ formsemestre = FormSemestre.get_formsemestre(formsemestre_id) assert formsemestre.formation.is_apc() title = "Procès-verbal de jury BUT" if fmt == "html": line_sep = "<br>" else: line_sep = "\n" rows, titles = pvjury_table_but(formsemestre, line_sep=line_sep) if fmt.startswith("xls"): titles.update( { "etudid": "etudid", "code_nip": "nip", "code_ine": "ine", "ects_but": "Total ECTS BUT", "civilite": "Civ.", "nom": "Nom", "prenom": "Prénom", } ) # Style excel... passages à la ligne sur \n xls_style_base = sco_excel.excel_make_style() xls_style_base["alignment"] = Alignment(wrapText=True, vertical="top") tab = GenTable( base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}", caption=title, columns_ids=titles.keys(), html_caption=title, html_class="pvjury_table_but table_leftalign", html_title=f"""<div style="margin-bottom: 8px;"><span style="font-size: 120%; font-weight: bold;">{title}</span> <span style="padding-left: 20px;"> <a href="{url_for("notes.pvjury_page_but", scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, fmt="xlsx")}" class="stdlink">version excel</a></span></div> """, html_with_td_classes=True, origin=f"Généré par {scu.sco_version.SCONAME} le {scu.timedate_human_repr()}", page_title=title, pdf_title=title, preferences=sco_preferences.SemPreferences(), rows=rows, table_id="formation_table_recap", titles=titles, xls_columns_width={ "nom": 32, "cursus": 12, "ues": 32, "niveaux": 32, "decision_but": 14, "diplome": 17, "devenir": 8, "observations": 12, }, xls_style_base=xls_style_base, ) return tab.make_page(fmt=fmt, javascripts=["js/etud_info.js"], init_qtip=True) def pvjury_table_but( formsemestre: FormSemestre, etudids: list[int] = None, line_sep: str = "\n", only_diplome=False, anonymous=False, with_paragraph_nom=False, ) -> tuple[list[dict], dict]: """Table avec résultats jury BUT pour PV. Si etudids est None, prend tous les étudiants inscrits. """ # remplace pour le BUT la fonction sco_pv_forms.pvjury_table annee_but = (formsemestre.semestre_id + 1) // 2 referentiel_competence_id = formsemestre.formation.referentiel_competence_id if referentiel_competence_id is None: raise ScoValueError( "pas de référentiel de compétences associé à la formation de ce semestre !" ) titles = { "nom_pv": "Code" if anonymous else "Nom", "cursus": "Cursus", "ects": "ECTS", "ues": "UE validées", "niveaux": "Niveaux de compétences validés", "decision_but": f"Décision BUT{annee_but}", "diplome": "Résultat au diplôme", "devenir": "Devenir", "observations": "Observations", } rows = [] formsemestre_etudids = formsemestre.etuds_inscriptions.keys() if etudids is None: etudids = formsemestre_etudids for etudid in etudids: if not etudid in formsemestre_etudids: continue # garde fou etud = Identite.get_etud(etudid) try: deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre) if deca.annee_but != annee_but: # wtf ? log( f"pvjury_table_but: inconsistent annee_but {deca.annee_but} != {annee_but}" ) continue except ScoValueError: deca = None ects_but_valides = but_ects_valides(etud, referentiel_competence_id) row = { "nom_pv": ( etud.code_ine or etud.code_nip or etud.id if anonymous # Mode anonyme: affiche INE ou sinon NIP, ou id else etud.etat_civil_pv( line_sep=line_sep, with_paragraph=with_paragraph_nom ) ), "_nom_pv_order": etud.sort_key, "_nom_pv_target_attrs": f'class="etudinfo" id="{etud.id}"', "_nom_pv_td_attrs": f'id="{etud.id}" class="etudinfo"', "_nom_pv_target": url_for( "scolar.fiche_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id, ), "cursus": _descr_cursus_but(etud), "ects": f"""{deca.ects_annee():g}<br><br>Tot. {ects_but_valides:g}""", "_ects_xls": deca.ects_annee(), "ects_but": ects_but_valides, "ues": deca.descr_ues_validation(line_sep=line_sep) if deca else "-", "niveaux": ( deca.descr_niveaux_validation(line_sep=line_sep) if deca else "-" ), "decision_but": deca.code_valide if deca else "", "devenir": ( ", ".join([f"S{i}" for i in deca.get_autorisations_passage()]) if deca else "" ), # pour exports excel seulement: "civilite": etud.civilite_etat_civil_str, "nom": etud.nom, "prenom": etud.prenom_etat_civil or etud.prenom or "", "etudid": etud.id, "code_nip": etud.code_nip, "code_ine": etud.code_ine, } if deca.valide_diplome() or not only_diplome: rows.append(row) rows.sort(key=lambda x: x["_nom_pv_order"]) return rows, titles