From 6fc3e16bdf9b9bf420eb074d728789cadb0fa6e5 Mon Sep 17 00:00:00 2001 From: Jean-Marie Place Date: Wed, 21 Jun 2023 07:37:08 +0200 Subject: [PATCH] wip --- app/but/prepajury_but.py | 255 +++++++++++++++++++++++---------- app/but/prepajury_desc.py | 170 ++++++++++++++++++++-- app/but/prepajury_xl.py | 13 +- app/but/prepajury_xl_format.py | 1 + app/views/notes.py | 86 +++++++++-- 5 files changed, 429 insertions(+), 96 deletions(-) diff --git a/app/but/prepajury_but.py b/app/but/prepajury_but.py index cf1db73d4..4f6dda329 100644 --- a/app/but/prepajury_but.py +++ b/app/but/prepajury_but.py @@ -32,8 +32,10 @@ import time from flask import flash, abort +from app.but import jury_but from app.but.cursus_but import EtudCursusBUT -from app.but.prepajury_desc import ParcoursDesc +from app.but.jury_but import DecisionsProposeesAnnee +from app.but.prepajury_desc import ParcoursDesc, liste_annees, FormSemestreDesc from app.comp import res_sem from app.comp.res_but import ResultatsSemestreBUT from app.models import ( @@ -48,101 +50,198 @@ import app.scodoc.sco_utils as scu from app.but.prepajury_xl import ScoExcelBook -class _Bilan: +class Element: def __init__(self): - self.note = 0 - self.resultat = 0 + self.note = None + self.resultat = None self.format = 0 + def set_note(self, note): + self.note = note -class _UE: + def set_res(self, res): + self.res = res + + def get_res(self): + return self.res + + def get_note(self): + return self.note + + +class ElementUE(Element): def __init__(self): - self.bilan = None + super().__init__() -class _Niveau: +class ElementNiveau(Element): def __init__(self, etudiant, niveauDesc, semestres): - self.bilan = None + super().__init__() self.etudiant = etudiant self.candidates = niveauDesc.get_ues(etudiant) self.ues = collections.defaultdict(list) def add_ue_status(self, semestre_idx, status): + ue_id = status["ue"]["id"] self.ues[semestre_idx].append(status) + self.etudiant.ues[ue_id] = status -class _Annee: +class ElementAnnee(Element): def __init__(self, etudiant, annee_desc): + super().__init__() self.etudiant = etudiant self.anneeDesc = annee_desc - self.bilan: _Bilan = None self.niveaux = {} -class _Competence: +class CompetenceEtudiantJury: def __init__(self, etudiant, competenceDesc, semestres): self.descr = competenceDesc self.etudiant = etudiant self.niveaux = {} for niveau_id, niveauDesc in competenceDesc.niveaux.items(): - self.niveaux[niveau_id] = _Niveau(etudiant, niveauDesc, semestres) + self.niveaux[niveau_id] = ElementNiveau(etudiant, niveauDesc, semestres) + etudiant.niveaux[niveau_id] = self.niveaux[niveau_id] def getNiveau(self, niveau_id): return self.niveaux[niveau_id] -class _Semestre: - def __init__(self, formsemestre_id, formsemestre=None): +class ElementFormsemestre(Element): + def __init__(self, formsemestre_id=None, formsemestre=None): + super().__init__() if formsemestre is None: formsemestre = FormSemestre.get_formsemestre(formsemestre_id) self.formsemestre = formsemestre - self.resultatsSemestreBUT: ResultatsSemestreBUT = ( - res_sem.load_formsemestre_results(formsemestre) - ) - # self.etuds_ues = ( - # self.resultatsSemestreBUT.load_ues_inscr_parcours() - # ) + self.deca = None + + def get_deca(self): + if self.deca is None: + self.deca = 0 + return self.deca -class _Etudiant: - def __init__(self, ident, formation): +class ListeElements: + def __init__(self): + self.elements = [] + + def add(self, element): + self.elements.append(element) + + def last(self): + return self.elements[-1] + + +class EtudiantJury: + def __init__(self, ident, formation, current_formsemestre, contexte): + self.contexte = contexte self.ident = ident - self.cursus: EtudCursusBUT = EtudCursusBUT(ident, formation) + self.formsemestre = current_formsemestre self.formsemestres = [] + self.formation = formation + self.cursus: EtudCursusBUT = EtudCursusBUT(ident, formation) self.parcour = self.cursus.inscriptions[-1].parcour + # Variables calculées self.history = [] - self.competences = {} - self.annees = [] - for inscription in self.cursus.inscriptions: + # + self.formsemestre_par_semestre_idx = collections.defaultdict(lambda: ListeElements()) + # self.niveau_par_annee_et_competence : list(ListeElements) = {} + self.ues_par_annee_et_competence : list(ListeElements) = {} + # + for inscription in sorted( + self.cursus.inscriptions, key=lambda x: x.formsemestre.date_debut + ): formsemestre = inscription.formsemestre - self.formsemestres.append(inscription.formsemestre.id) + element_formsemestre = contexte.get_element_formsemestre(formsemestre.formsemestre_id) Sx = f"S{formsemestre.semestre_id}" + self.formsemestre_par_semestre_idx[formsemestre.semestre_id].add(formsemestre) etat = inscription.etat if etat != "I": - Sx += "(Dem)" if etat == "D" else f"({etat})" + Sx += " (Dem)" if etat == "D" else f" ({etat})" self.history.append(Sx) + def select(self, annee_idx=None, periode_idx=None, competence_id=None): + pass + def fill_in(self, parcourDescr, semestres): - self.annees = { - codeAnnee: _Annee(self, anneeDesc) - for codeAnnee, anneeDesc in parcourDescr.annees.items() - } - for (competence_id, competenceDesc) in parcourDescr.competences.items(): - self.competences[competence_id] = _Competence( - self, competenceDesc, semestres - ) + # Remplissage des competences + # Remplissage des formsemestres for formsemestre_id in self.formsemestres: - semestre: _Semestre = semestres[formsemestre_id] - ues = semestre.resultatsSemestreBUT.etud_ues(self.ident.etudid) - for ue in ues: - niveau_id = ue.niveau_competence_id - competence_id = ue.niveau_competence.competence_id - semestre_idx = ue.semestre_idx - niveau = self.competences[competence_id].getNiveau(niveau_id) - status = semestre.resultatsSemestreBUT.get_etud_ue_status( - self.ident.etudid, ue.id - ) - niveau.add_ue_status(semestre_idx, status) + formsemestre_desc = self.contexte.get_element_formsemestre(formsemestre_id) + semestre_idx = formsemestre_desc.formsemestre.semestre_id + self.formsemestre_par_semestre_idx[semestre_idx] = formsemestre_desc + for semestre_idx in range(1, 6): + if semestre_idx in self.formsemestre_par_semestre_idx: + formsemestre_desc = self.formsemestre_par_semestre_idx[semestre_idx] + resultats = formsemestre_desc.get_resultats() + ues = resultats.etud_ues(self.ident.etudid) + for ue in ues: + competence_id = ue.niveau_competence.competence_id + status = resultats.get_etud_ue_status( + self.ident.etudid, ue.id + ) + self.ues_par_competence_et_annee[(semestre_idx, competence_id)] = status + pass + + # deca = DecisionsProposeesAnnee(self.ident, formsemestre) + # Remplissage des niveaux de compétence + # for (competence_id, item) in self.cursus.validation_par_competence_et_annee.items(): + # for (annee, validation) in item.items(): + # self.niveau_par_annee_and_competence[(annee, competence_id)].res = validation.code + # for annee, idx in [("BUT1", 1), ("BUT2", 2), ("BUT3", 3)]: + # formsemestre = self.formsemestre_par_semestre_idx.get(idx + 1, self.formsemestre_par_semestre_idx.get(idx, None)) + # if formsemestre is not None: + # deca = DecisionsProposeesAnnee(self.ident, formsemestre) + + # for (competence_id, competenceDesc) in parcourDescr.competences.items(): + # self.competences[competence_id] = CompetenceEtudiantJury( + # self, competenceDesc, semestres + # ) + # self.annees = { + # codeAnnee: _Annee(self, anneeDesc) + # for codeAnnee, anneeDesc in parcourDescr.annees.items() + # } + # for semestre, annee in [(2, "BUT1"), (4, "BUT2"), (6, "BUT3")]: + # if semestre in self.formsemestre_par_semestre_idx: + # self.deca[annee] = jury_but.DecisionsProposeesAnnee( + # self.ident, self.formsemestre_par_semestre_idx[semestre] + # ) + # elif semestre - 1 in self.formsemestre_par_semestre_idx: + # self.deca[annee] = jury_but.DecisionsProposeesAnnee( + # self.ident, self.formsemestre_par_semestre_idx[semestre - 1] + # ) + # if annee in self.deca: + # for rcue in self.deca[annee].rcues_annee: + # ue_id1 = rcue.ue_1.id + # self.notes_ues[ue_id1] = rcue.moy_ue_1 + # ue_id2 = rcue.ue_2.id + # self.notes_ues[ue_id2] = rcue.moy_ue_2 + # rcue_id = rcue.ue_1.niveau_competence_id + # self.notes_rcues[rcue_id] = rcue.moy_rcue + + def add_formsemestre(self, formsemestre_id): + self.formsemestres.append(formsemestre_id) + + def getDipl(self, codeAnnée): + return "" + + def getNote(self, codeAnnée, niveau_id=None, ue_id=None): + annee = self.annees.get(codeAnnée, None) + if annee is None: + return "-" + if niveau_id is None: + return "" + elif ue_id is None: + return self.notes_rcues.get(niveau_id, "") + return self.notes_ues.get(ue_id, "") + + def getRes(self, codeAnnée, niveau_id=None, ue_id=None): + if niveau_id is None: + return "" + elif ue_id is None: + return "" + return "" def getData(self): result = [ @@ -160,53 +259,63 @@ class _Etudiant: class _Compilation: def __init__(self, formsemestre: FormSemestre): - self.semestres = {} - self.parcours = {} + # Dictionnaire des éléments + self.inv_formsemestres = {} + # self.inv_niveaux = {} + # self.inv_ues = {} + # self.inv_annees = {} + self.inv_parcours = {} + # formsemestre_id = formsemestre.formsemestre_id - self.semestre: _Semestre = _Semestre(formsemestre_id, formsemestre) self.formation: Formation = formsemestre.formation - self.add_semestre(formsemestre_id, self.semestre) - for ident in self.semestre.resultatsSemestreBUT.get_inscrits(order_by="moy"): - etudiant: _Etudiant = _Etudiant(ident, self.formation) - for inscription in etudiant.cursus.inscriptions: + self.consider_formsemestre(formsemestre=formsemestre) + formsemestre_desc = self.get_element_formsemestre(formsemestre_id) + for ident in formsemestre_desc.get_resultats().get_inscrits(order_by="moy"): + etudiant: EtudiantJury = EtudiantJury(ident, self.formation, formsemestre, self) + # Ajout de tous les semestres de l'étudiant + for inscription in sorted(etudiant.cursus.inscriptions, key=lambda x: x.formsemestre.date_debut): formsemestre = inscription.formsemestre if ( - formsemestre.formation.referentiel_competence - == self.formation.referentiel_competence + formsemestre.formation.referentiel_competence + == self.formation.referentiel_competence ): - self.add_semestre(formsemestre.id) + self.consider_formsemestre(formsemestre=formsemestre) + etudiant.add_formsemestre(formsemestre.formsemestre_id) + # Prise en compte du parcours scodocParcour = etudiant.parcour if scodocParcour is None: parcourCode = "TC" else: parcourCode = scodocParcour.code - if parcourCode in self.parcours: - parcoursDesc = self.parcours[parcourCode] + if parcourCode in self.inv_parcours: + parcoursDesc = self.inv_parcours[parcourCode] else: parcoursDesc = ParcoursDesc(self.formation, scodocParcour) - self.parcours[parcourCode] = parcoursDesc + self.inv_parcours[parcourCode] = parcoursDesc parcoursDesc.add_etudiant(etudiant) - # etudiant.fill_in(parcoursDesc, self.semestres) - pass + etudiant.fill_in(parcoursDesc, self) - def add_semestre(self, formsemestre_id, semestre: _Semestre = None): - if not formsemestre_id in self.semestres: + def get_element_formsemestre(self, formsemestre_id): + return self.inv_formsemestres.get(formsemestre_id, None) + + def consider_formsemestre(self, formsemestre: FormSemestre): + formsemestre_id = formsemestre.formsemestre_id + if formsemestre_id not in self.inv_formsemestres: + formsemestre_desc = FormSemestreDesc(formsemestre) + self.inv_formsemestres[formsemestre_id] = formsemestre_desc + + def add_semestre(self, formsemestre_id, semestre: ElementFormsemestre = None): + if not formsemestre_id in self.ElemFormSemestres: if semestre is None: - semestre = _Semestre(formsemestre_id) - self.semestres[formsemestre_id] = _Semestre(formsemestre_id) - - def add_parcours(self, scodocParcour: ApcParcours, etudiant: _Etudiant): - parcour_code = scodocParcour.get("code", "TC") - if not parcour_code in self.parcours: - self.parcours[parcour_code] = ParcoursDesc(self.formation, scodocParcour) - self.parcours[parcour_code].add(etudiant) + semestre = ElementFormsemestre(formsemestre_id) + self.ElemFormSemestres[formsemestre_id] = ElementFormsemestre(formsemestre_id) def computes_decision(self): pass def make_excel(self, filename: str): workbook = ScoExcelBook() - for parcoursCode, parcours in self.parcours.items(): + for parcoursCode, parcours in self.inv_parcours.items(): parcours.generate(workbook) mime, suffix = scu.get_mime_suffix("xlsx") diff --git a/app/but/prepajury_desc.py b/app/but/prepajury_desc.py index 820604a8a..53125d909 100644 --- a/app/but/prepajury_desc.py +++ b/app/but/prepajury_desc.py @@ -1,5 +1,6 @@ import openpyxl from openpyxl.worksheet.worksheet import Worksheet + from app.but.prepajury_xl_format import ( SCO_COLORS, FMT, @@ -11,6 +12,8 @@ from app.but.prepajury_xl_format import ( HAIR_BLACK, SCO_NUMBER_FORMAT, ) +from app.comp import res_sem +from app.comp.res_but import ResultatsSemestreBUT from app.models import ApcCompetence, ApcParcours from app.but.prepajury_xl import ( ScoExcelBook, @@ -21,11 +24,8 @@ from app.but.prepajury_xl import ( ) -def parite(semestre_idx): - return (semestre_idx + 1) % 2 - - -listeAnnees = ["BUT1", "BUT2", "BUT3"] +UNUSED = "XXX" +liste_annees = ["BUT1", "BUT2", "BUT3"] header_colors = { "BUT1": { "BUT": SCO_COLORS.BUT1, @@ -45,6 +45,25 @@ header_colors = { } +def parite(semestre_idx): + return (semestre_idx + 1) % 2 + + +class FormSemestreDesc: + def __init__(self, formsemestre): + self.formsemestre = formsemestre + self.deca = None + self.resultats = None + + def get_resultats(self): + if self.resultats is None: + self.resultats: ResultatsSemestreBUT = ( + res_sem.load_formsemestre_results(self.formsemestre) + ) + return self.resultats + + + class NiveauDesc: def __init__(self, scodocNiveau): self.fromScodoc = scodocNiveau @@ -55,6 +74,93 @@ class NiveauDesc: if not scodocUe.is_external: self.ue[parite(scodocUe.semestre_idx)] = scodocUe + def generate_data( + self, ws: ScoExcelSheet, row: int, etudiant: "EtudiantJury", column: int + ) -> int: + for ue in self.ue: + if ue is None: + ws.set_cell(row, column, UNUSED) + ws.set_cell(row, column + 1, UNUSED) + else: + ws.set_cell( + row, + column, + etudiant.getNote(self.fromScodoc.annee, self.fromScodoc.id, ue.id), + base_signature, + ) + ws.set_cell( + row, + column + 1, + etudiant.getRes(self.fromScodoc.annee, self.fromScodoc.id, ue.id), + ) + column += 2 + ws.set_cell( + row, + column, + etudiant.getNote(self.fromScodoc.annee, self.fromScodoc.id), + base_signature, + ) + ws.set_cell( + row, column + 1, etudiant.getRes(self.fromScodoc.annee, self.fromScodoc.id) + ) + return column + 2 + + @staticmethod + def generate_blank_data(ws: ScoExcelSheet, row: int, column: int) -> int: + ws.set_cell(row, column + 0, "UN1") + ws.set_cell(row, column + 1, "UR1") + ws.set_cell(row, column + 2, "UN2") + ws.set_cell(row, column + 3, "UR2") + ws.set_cell(row, column + 4, "R1") + ws.set_cell(row, column + 5, "R2") + column += 6 + return column + + @staticmethod + def generate_blank_header(ws: ScoExcelSheet, column: int, annee: str): + rcue_signature = FMT.FILL_BGCOLOR.write( + value=header_colors[annee]["RCUE"].value, + signature=base_signature, + ) + ue_signature = FMT.FILL_BGCOLOR.write( + value=header_colors[annee]["UE"].value, + signature=base_signature, + ) + merge = ws.get_merge_engine(start_row=2, start_column=column) + frame = ws.get_frame_engine( + start_row=2, start_column=column, thickness=SCO_BORDERTHICKNESS.BORDER_THIN + ) + ws.set_cell(2, column, UNUSED, from_signature=rcue_signature) + for ue in ["UE1", "UE2"]: + frame_ue = ws.get_frame_engine( + start_row=3, + start_column=column, + thickness=SCO_BORDERTHICKNESS.BORDER_THIN, + color=SCO_COLORS.GREY, + ) + merge_ue = ws.get_merge_engine(start_row=3, start_column=column) + ws.set_cell(3, column, UNUSED, ue_signature) + ws.set_cell(4, column, "Note", ue_signature) + ws.set_column_dimension_hidden(ScoExcelSheet.i2col(column - 1), True) + column += 1 + ws.set_cell(4, column, "Rés.", ue_signature) + ws.set_column_dimension_hidden(ScoExcelSheet.i2col(column - 1), True) + column += 1 + merge_ue.close(end_row=3, end_column=column - 1) + frame_ue.close(end_row=4, end_column=column - 1) + merge_rcue = ws.get_merge_engine(start_row=3, start_column=column) + ws.set_cell(3, column, UNUSED, rcue_signature) + ws.set_cell(4, column, UNUSED, rcue_signature) + ws.set_column_dimension_hidden(ScoExcelSheet.i2col(column - 1), True) + column += 1 + ws.set_cell(4, column, UNUSED, rcue_signature) + ws.set_column_dimension_hidden(ScoExcelSheet.i2col(column - 1), True) + column += 1 + merge_rcue.close(end_row=3, end_column=column - 1) + frame.close(end_row=4, end_column=column - 1) + merge.close(end_row=2, end_column=column - 1) + return column + def generate_header(self, ws: ScoExcelSheet, column: int): rcue_signature = FMT.FILL_BGCOLOR.write( value=header_colors[self.fromScodoc.annee]["RCUE"].value, @@ -68,7 +174,9 @@ class NiveauDesc: frame = ws.get_frame_engine( start_row=2, start_column=column, thickness=SCO_BORDERTHICKNESS.BORDER_THIN ) - ws.set_cell(2, column, self.fromScodoc.libelle, from_signature=rcue_signature) + ws.set_cell( + 2, column, self.fromScodoc.competence.titre, from_signature=rcue_signature + ) for ue in self.ue: frame_ue = ws.get_frame_engine( start_row=3, @@ -140,6 +248,25 @@ class AnneeDesc: def generate_blank_niveau(self, ws: ScoExcelSheet, column: int): return column + def generate_data( + self, ws: ScoExcelSheet, row: int, etudiant: "EtudiantJury", column: int + ) -> int: + for niveau in self.niveaux.values(): + column = niveau.generate_data(ws, row, etudiant, column) + for i in range(len(self.niveaux), 6): + column = NiveauDesc.generate_blank_data(ws, row, column) + ws.set_cell(row, column + 0, "A1") + ws.set_cell(row, column + 1, etudiant.getNote(self.codeAnnee), base_signature) + ws.set_cell(row, column + 2, etudiant.getRes(self.codeAnnee)) + column += 3 + if self.codeAnnee == "BUT2": + ws.set_cell(row, column, etudiant.getDipl("BUT2")) + column += 1 + if self.codeAnnee == "BUT3": + ws.set_cell(row, column, etudiant.getDipl("BUT3")) + column += 1 + return column + def generate_header(self, ws: ScoExcelSheet, column: int): start = column but_signature = FMT.FILL_BGCOLOR.write( @@ -162,7 +289,7 @@ class AnneeDesc: for niveau in self.niveaux.values(): column = niveau.generate_header(ws, column) for i in range(len(self.niveaux), 6): - column = self.generate_blank_niveau(ws, column) + column = NiveauDesc.generate_blank_header(ws, column, self.codeAnnee) merge_annee = ws.get_merge_engine(start_row=2, start_column=column) ws.set_cell(2, column, "Année", from_signature=but_signature) # cell_format(ws.cell(2, column), but_signature, [(FMT.FONT_BOLD, True)]) @@ -227,7 +354,7 @@ class ParcoursDesc: self.competences[scodocCompetence.id] = CompetenceDesc( scodocCompetence ) - for codeAnnee in listeAnnees: + for codeAnnee in liste_annees: anneeDesc = AnneeDesc(codeAnnee) for competence_id, competence in self.competences.items(): anneeDesc.addNiveau(competence.getNiveaux(codeAnnee)) @@ -312,7 +439,7 @@ class ParcoursDesc: def generate_header(self, ws: ScoExcelSheet): column: int = self.generate_etudiant_header(ws) - for codeAnnee in listeAnnees: + for codeAnnee in liste_annees: column = self.annees[codeAnnee].generate_header(ws, column) def generate(self, workbook: ScoExcelBook): @@ -322,3 +449,28 @@ class ParcoursDesc: sheet_name = "TC" worksheet: ScoExcelSheet = workbook.create_sheet(sheet_name) self.generate_header(worksheet) + self.generate_etudiants(worksheet) + + def generate_data( + self, ws: ScoExcelSheet, row: int, column: int, etudiant: "EtudiantJury" + ): + for codeAnnee in liste_annees: + column = self.annees[codeAnnee].generate_data(ws, row, etudiant, column) + ws.set_cell(row, column, "FIN") + + def generate_etudiants(self, ws: ScoExcelSheet): + ligne = 5 + for etudiant in self.etudiants: + ws.set_cell(ligne, 1, etudiant.ident.id) + ws.set_cell(ligne, 2, etudiant.ident.code_nip) + ws.set_cell(ligne, 3, etudiant.ident.civilite) + ws.set_cell(ligne, 4, etudiant.ident.nom) + ws.set_cell(ligne, 5, etudiant.ident.prenom) + if etudiant.parcour: + ws.set_cell(ligne, 6, etudiant.parcour.code) + else: + ws.set_cell(ligne, 6, "-") + cursus = ", ".join(etudiant.history) + ws.set_cell(ligne, 7, cursus) + self.generate_data(ws, ligne, 10, etudiant) + ligne = ligne + 1 diff --git a/app/but/prepajury_xl.py b/app/but/prepajury_xl.py index 058229d65..007022ae4 100644 --- a/app/but/prepajury_xl.py +++ b/app/but/prepajury_xl.py @@ -284,9 +284,9 @@ class ScoExcelSheet: if idx < 26: # one letter key return chr(idx + 65) else: # two letters AA..ZZ - first = (idx // 26) + 66 - second = (idx % 26) + 65 - return "" + chr(first) + chr(second) + first = idx // 26 + second = idx % 26 + return "" + chr(first + 64) + chr(second + 65) def set_cell( self, @@ -332,6 +332,13 @@ class ScoExcelSheet: """ self.ws.row_dimensions[cle].hidden = value + def set_column_dimension_hidden(self, cle, value): + """Masque ou affiche une ligne. + cle -- identifie la colonne (1...) + value -- boolean (vrai = colonne cachée) + """ + self.ws.column_dimensions[cle].hidden = value + # def make_cell(self, value: any = None, style: Sco_Style = None, comment=None): # """Construit une cellule. # value -- contenu de la cellule (texte, numérique, booléen ou date) diff --git a/app/but/prepajury_xl_format.py b/app/but/prepajury_xl_format.py index 0e30fead2..5579af127 100644 --- a/app/but/prepajury_xl_format.py +++ b/app/but/prepajury_xl_format.py @@ -90,6 +90,7 @@ class SCO_NUMBER_FORMAT(Enum): NONE = (0, None) NUMBER_GENERAL = (0, FORMAT_GENERAL) NUMBER_00 = (1, FORMAT_NUMBER_00) + NUMBER_0 = (2, "0.0") class SCO_HALIGN(Enum): diff --git a/app/views/notes.py b/app/views/notes.py index 4d8c38914..8534c8418 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -47,11 +47,12 @@ from app.but import jury_but, jury_but_validation_auto from app.but.forms import jury_but_forms from app.but import jury_but_pv from app.but import jury_but_view +from app.but import jury_edit_manual -from app.comp import res_sem +from app.comp import jury, res_sem from app.comp.res_compat import NotesTableCompat -from app.models import ScolarAutorisationInscription, ScolarNews, Scolog -from app.models.but_refcomp import ApcNiveau, ApcParcours +from app.models import Formation, ScolarAutorisationInscription, ScolarNews, Scolog +from app.models.but_refcomp import ApcNiveau from app.models.config import ScoDocSiteConfig from app.models.etudiants import Identite from app.models.formsemestre import FormSemestre @@ -2493,7 +2494,19 @@ def formsemestre_validation_but( erase_span = f"""effacer décisions""" + etudid=deca.etud.id)}" class="stdlink" + title="efface décisions issues des jurys de cette année" + >effacer décisions + + effacer toutes ses décisions de BUT{deca.annee_but} + """ H.append( f"""
@@ -2814,15 +2827,15 @@ def formsemestre_saisie_jury(formsemestre_id: int, selected_etudid: int = None): ) @scodoc @permission_required(Permission.ScoView) -def formsemestre_jury_but_erase( - formsemestre_id: int, etudid: int = None, only_one_sem=False -): +def formsemestre_jury_but_erase(formsemestre_id: int, etudid: int = None): """Supprime la décision de jury BUT pour cette année. - Si only_one_sem, n'efface que pour le formsemestre indiqué, pas les deux de l'année. Si l'étudiant n'est pas spécifié, efface les décisions de tous les inscrits. + Si only_one_sem, n'efface que pour le formsemestre indiqué, pas les deux de l'année. """ only_one_sem = int(request.args.get("only_one_sem") or False) - formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id) + formsemestre: FormSemestre = FormSemestre.query.filter_by( + id=formsemestre_id, dept_id=g.scodoc_dept_id + ).first_or_404() if not formsemestre.can_edit_jury(): raise ScoPermissionDenied( dest_url=url_for( @@ -2880,14 +2893,65 @@ def formsemestre_jury_but_erase( if only_one_sem else """Les validations de toutes les UE, RCUE (compétences) et année issues de cette année scolaire seront effacées. - Les décisions des années scolaires précédentes ne seront pas modifiées. """ ) - + """
Cette opération est irréversible !
""", + + """ +

Les décisions des années scolaires précédentes ne seront pas modifiées.

+
Cette opération est irréversible !
+ """, cancel_url=dest_url, ) +@bp.route( + "/erase_decisions_annee_formation///", + methods=["GET", "POST"], +) +@scodoc +@permission_required(Permission.ScoEtudInscrit) +def erase_decisions_annee_formation(etudid: int, formation_id: int, annee: int): + """Efface toute les décisions d'une année pour cet étudiant""" + etud: Identite = Identite.query.get_or_404(etudid) + formation: Formation = Formation.query.filter_by( + id=formation_id, dept_id=g.scodoc_dept_id + ).first_or_404() + if request.method == "POST": + jury.erase_decisions_annee_formation(etud, formation, annee, delete=True) + flash("Décisions de jury effacées") + return redirect( + url_for( + "scolar.ficheEtud", + scodoc_dept=g.scodoc_dept, + etudid=etud.id, + ) + ) + validations = jury.erase_decisions_annee_formation(etud, formation, annee) + return render_template( + "jury/erase_decisions_annee_formation.j2", + annee=annee, + cancel_url=url_for( + "scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etud.id + ), + etud=etud, + formation=formation, + validations=validations, + sco=ScoData(), + title=f"Effacer décisions de jury {etud.nom} - année {annee}", + ) + + +@bp.route( + "/jury_delete_manual/", + methods=["GET", "POST"], +) +@scodoc +@permission_required(Permission.ScoEtudInscrit) +def jury_delete_manual(etudid: int): + """Efface toute les décisions d'une année pour cet étudiant""" + etud: Identite = Identite.query.get_or_404(etudid) + return jury_edit_manual.jury_delete_manual(etud) + + sco_publish( "/formsemestre_lettres_individuelles", sco_pv_forms.formsemestre_lettres_individuelles,