Skip to content
Snippets Groups Projects
Select Git revision
  • dae04658b767b9a7194f9d8dda8823de9d91f77c
  • master default protected
2 results

visu_assiduites.py

Blame
  • Forked from Jean-Marie Place / SCODOC_R6A06
    Source project has a limited visibility.
    visu_assiduites.py 5.91 KiB
    ##############################################################################
    # ScoDoc
    # Copyright (c) 1999 - 2024 Emmanuel Viennet.  All rights reserved.
    # See LICENSE
    ##############################################################################
    
    """Liste simple d'étudiants
    """
    
    from flask import g, url_for
    from app import log
    from app.models import FormSemestre, Identite, Justificatif
    from app.tables import table_builder as tb
    import app.scodoc.sco_assiduites as scass
    from app.scodoc import sco_preferences
    from app.scodoc import sco_utils as scu
    
    
    class TableAssi(tb.Table):
        """Table listant les statistiques d'assiduité des étudiants
        L'id de la ligne est etuid, et le row stocke etud.
        """
    
        def __init__(
            self,
            etuds: list[Identite] = None,
            dates: tuple[str, str] = None,
            formsemestre: FormSemestre = None,
            **kwargs,
        ):
            self.rows: list["RowEtud"] = []  # juste pour que VSCode nous aide sur .rows
            classes = ["gt_table"]
            self.dates = [str(dates[0]) + "T00:00", str(dates[1]) + "T23:59"]
            self.formsemestre = formsemestre
            super().__init__(
                row_class=RowAssi,
                classes=classes,
                **kwargs,
                with_foot_titles=False,
            )
            self.add_etuds(etuds)
    
        def add_etuds(self, etuds: list[Identite]):
            "Ajoute des étudiants à la table"
            for etud in etuds:
                row = self.row_class(self, etud)
                row.add_etud_cols()
                self.add_row(row)
    
    
    class RowAssi(tb.Row):
        "Ligne de la table assiduité"
    
        # pour le moment très simple, extensible (codes, liens bulletins, ...)
        def __init__(self, table: TableAssi, etud: Identite, *args, **kwargs):
            # Etat de l'inscription au formsemestre
            if "classes" not in kwargs:
                kwargs["classes"] = []
            try:
                inscription = table.formsemestre.etuds_inscriptions[etud.id]
                if inscription.etat == scu.DEMISSION:
                    kwargs["classes"].append("etuddem")
            except KeyError:
                log(f"RowAssi: etudid {etud.id} non inscrit à {table.formsemestre.id}")
                kwargs["classes"].append("non_inscrit")  # ne devrait pas arriver !
    
            super().__init__(table, etud.id, *args, **kwargs)
            self.etud = etud
            self.dates = table.dates
    
        def add_etud_cols(self):
            """Ajoute les colonnes"""
            etud = self.etud
            self.table.group_titles.update(
                {
                    "etud_codes": "Codes",
                    "identite_detail": "",
                    "identite_court": "",
                }
            )
    
            bilan_etud = url_for(
                "assiduites.bilan_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id
            )
            self.add_cell(
                "nom_disp",
                "Nom",
                etud.nom_disp(),
                "etudinfo",
                attrs={"id": str(etud.id)},
                data={"order": etud.sort_key},
                target=bilan_etud,
                target_attrs={"class": "discretelink"},
            )
            self.add_cell(
                "prenom",
                "Prénom",
                etud.prenom_str,
                "etudinfo",
                attrs={"id": str(etud.id)},
                data={"order": etud.sort_key},
                target=bilan_etud,
                target_attrs={"class": "discretelink"},
            )
            stats = self._get_etud_stats(etud)
            for key, value in stats.items():
                self.add_cell(key, value[0], f"{value[1] - value[2]}", "assi_stats")
                if key != "present":
                    self.add_cell(
                        key + "_justi",
                        value[0] + " Justifiées",
                        f"{value[2]}",
                        "assi_stats",
                    )
    
            compte_justificatifs = scass.filter_by_date(
                etud.justificatifs, Justificatif, self.dates[0], self.dates[1]
            )
    
            compte_justificatifs_att = compte_justificatifs.filter(Justificatif.etat == 2)
    
            self.add_cell(
                "justificatifs_att",
                "Justificatifs en Attente",
                f"{compte_justificatifs_att.count()}",
            )
            self.add_cell(
                "justificatifs", "Justificatifs", f"{compte_justificatifs.count()}"
            )
    
        def _get_etud_stats(self, etud: Identite) -> dict[str, list[str, float, float]]:
            """
            Renvoie le comptage (dans la métrique du département) des différents états d'assiduité d'un étudiant
    
            Returns :
                {
                    "<etat>" : [<Etat version lisible>, <nb total etat>, <nb just etat>]
                }
    
            """
    
            # Préparation du retour
            retour: dict[str, tuple[str, float, float]] = {
                "absent": ["Absences", 0.0, 0.0],
                "retard": ["Retards", 0.0, 0.0],
                "present": ["Présences", 0.0, 0.0],
            }
    
            # Récupération de la métrique du département
            assi_metric = scu.translate_assiduites_metric(
                sco_preferences.get_preference("assi_metrique", dept_id=g.scodoc_dept_id),
            )
    
            compte_etat: dict[str, dict] = scass.get_assiduites_stats(
                assiduites=etud.assiduites,
                metric=assi_metric,
                filtered={
                    "date_debut": self.dates[0],
                    "date_fin": self.dates[1],
                    "etat": "absent,present,retard",  # pour tout compter d'un coup
                    "split": 1,  # afin d'avoir la division des stats en état, etatjust, etatnonjust
                },
            )
    
            # Pour chaque état on met à jour les valeurs de retour
            for etat, valeur in retour.items():
                valeur[1] = compte_etat[etat][assi_metric]
                if etat != "present":
                    valeur[2] = compte_etat[etat]["justifie"][assi_metric]
            return retour
    
    
    def etuds_sorted_from_ids(etudids) -> list[Identite]:
        "Liste triée d'etuds à partir d'une collections d'etudids"
        etuds = [Identite.get_etud(etudid) for etudid in etudids]
        return sorted(etuds, key=lambda etud: etud.sort_key)