import openpyxl from openpyxl.worksheet.worksheet import Worksheet from app.but.prepajury_cells import Sco_Cell, base_signature, set_cell from app.but.prepajury_xl_format import ( SCO_COLORS, FMT, SCO_FONTSIZE, SCO_VALIGN, SCO_HALIGN, SCO_BORDERTHICKNESS, Sco_Style, ) from app.models import ApcCompetence, ApcParcours from app.but.prepajury_xl import ScoExcelBook, ScoExcelSheet def parite(semestre_idx): return (semestre_idx + 1) % 2 listeAnnees = ["BUT1", "BUT2", "BUT3"] header_colors = { "BUT1": { "BUT": SCO_COLORS.BUT1, "RCUE": SCO_COLORS.RCUE1, "UE": SCO_COLORS.UE1, }, "BUT2": { "BUT": SCO_COLORS.BUT2, "RCUE": SCO_COLORS.RCUE2, "UE": SCO_COLORS.UE2, }, "BUT3": { "BUT": SCO_COLORS.BUT3, "RCUE": SCO_COLORS.RCUE3, "UE": SCO_COLORS.UE3, }, } class _Header: def __init__(self): self.lines: list[list[Sco_Cell]] = [] self.presets = [None, None, None, None] self.signatures = [ base_signature, base_signature, base_signature, base_signature, ] def setLabelOnce(self, rang: int, label: str): self.presets[rang] = label def setSignatures(self, rangs: list[int], signature: int): for rang in rangs: self.signatures[rang] = signature def add_column( self, label0=None, label1=None, label2=None, label3=None, labels: list[str] = None, ): if labels is None: labels = [label0, label1, label2, label3] cells: list(Sco_Cell) = [ Sco_Cell(preset or label, signature=signature) for label, preset, signature in zip(labels, self.presets, self.signatures) ] self.presets = [None, None, None, None] self.lines.append(cells) def extend(self, header): self.lines.extend(header.lines) def write(self, worksheet: ScoExcelSheet): column = 1 for items in self.lines: items[0].copy(worksheet.ws.cell(1, column)) items[1].copy(worksheet.ws.cell(2, column)) items[2].copy(worksheet.ws.cell(3, column)) items[3].copy(worksheet.ws.cell(4, column)) column += 1 class NiveauDesc: def __init__(self, scodocNiveau): self.fromScodoc = scodocNiveau self.ues = {} self.ue = [None, None] for scodocUe in scodocNiveau.ues: self.ues[(scodocUe.formation_id, scodocUe.semestre_idx)] = scodocUe if not scodocUe.is_external: self.ue[parite(scodocUe.semestre_idx)] = scodocUe def generate_header(self, header): rcue_signature = FMT.FILL_BGCOLOR.write( value=header_colors[self.fromScodoc.annee]["RCUE"].value, signature=base_signature, ) ue_signature = FMT.FILL_BGCOLOR.write( value=header_colors[self.fromScodoc.annee]["UE"].value, signature=base_signature, ) header.setLabelOnce(1, self.fromScodoc.competence.titre) header.setSignatures([1], rcue_signature) header.setSignatures([2, 3], ue_signature) for ue in self.ue: if ue is None: header.setLabelOnce(2, "XXX") header.add_column(label3="Note") header.add_column(label3="Res.") else: header.setLabelOnce(2, ue.acronyme) header.add_column(label3="Note") header.add_column(label3="Res.") header.setSignatures([1, 2, 3], rcue_signature) header.add_column(label2="RCUE", label3="Note") header.add_column(label3="Res.") return header def get_ues(self, etudiant): """get list of candidates UEs for Niveau""" ues = [None, None] for inscription in etudiant.cursus.inscriptions: formation_id = inscription.formsemestre.formation_id semestre_idx = inscription.formsemestre.semestre_id if (formation_id, semestre_idx) in self.ues: # identifier les ues cocernées ues[semestre_idx % 2] = inscription.formsemestre return ues class CompetenceDesc: def __init__(self, scodocCompetence): self.fromScodoc: ApcCompetence = scodocCompetence self.niveaux = {} for scodocNiveau in scodocCompetence.niveaux.all(): self.niveaux[scodocNiveau.id] = NiveauDesc(scodocNiveau) def getNiveauDesc(self, niveau_id): return self.niveaux[niveau_id] def getNiveaux(self, codeAnnee): niveaux = [] for niveau_id, niveauDesc in self.niveaux.items(): if codeAnnee == niveauDesc.fromScodoc.annee: niveaux.append(niveauDesc) return niveaux class AnneeDesc: def __init__(self, codeAnnee): self.codeAnnee = codeAnnee self.niveaux = {} def addNiveau(self, niveaux): for niveau in niveaux: self.niveaux[niveau.fromScodoc.id] = niveau def generate_blank_niveau(self, header): header.setlabel(1, "-") for _ in range(3): header.add_column() def generate_header(self, ws: Worksheet, column: int, codeAnnee: str): start = column but_signature = FMT.FILL_BGCOLOR.write( signature=base_signature, value=header_colors[self.codeAnnee]["BUT"].value ) but_style = FMT.style(but_signature) set_cell( ws, 1, column, text=codeAnnee, from_signature=but_signature, composition=[ (FMT.BORDER_LEFT_COLOR, SCO_COLORS.BLACK.value), (FMT.BORDER_LEFT_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value), ], ) ws.cell(1, column).value = codeAnnee but_style.apply(ws.cell(1, column)) # 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) ws.cell(2, column).value = "Année" # cell_format(ws.cell(2, column), but_signature, [(FMT.FONT_BOLD, True)]) ws.cell(3, column).value = "Nb" ws.cell(4, column).value = "RCUE" column += 1 ws.cell(2, column).value = "Année" ws.cell(4, column).value = "Moy." column += 1 if self.codeAnnee == "BUT2": ws.cell(3, column).value = "DUT" ws.cell(3, column).value = "Rés." if self.codeAnnee == "BUT3": ws.cell(3, column).value = "BUT" ws.cell(3, column).value = "Rés." # ws.merge_cells(start_column=start, end_column=column, start_row=1, end_row=1) return column class ParcoursDesc: signature_header = FMT.compose( [ (FMT.FILL_BGCOLOR, SCO_COLORS.LIGHT_YELLOW.value), (FMT.FONT_BOLD, True), (FMT.FONT_SIZE, SCO_FONTSIZE.FONTSIZE_13.value), (FMT.ALIGNMENT_VALIGN, SCO_VALIGN.VALIGN_CENTER.value), (FMT.ALIGNMENT_HALIGN, SCO_HALIGN.HALIGN_CENTER.value), (FMT.BORDER_LEFT_STYLE, SCO_BORDERTHICKNESS.BORDER_THIN.value), (FMT.BORDER_RIGHT_STYLE, SCO_BORDERTHICKNESS.BORDER_THIN.value), (FMT.BORDER_TOP_STYLE, SCO_BORDERTHICKNESS.BORDER_THIN.value), (FMT.BORDER_BOTTOM_STYLE, SCO_BORDERTHICKNESS.BORDER_THIN.value), (FMT.BORDER_LEFT_COLOR, SCO_COLORS.BLACK.value), (FMT.BORDER_RIGHT_COLOR, SCO_COLORS.BLACK.value), (FMT.BORDER_TOP_COLOR, SCO_COLORS.BLACK.value), (FMT.BORDER_RIGHT_COLOR, SCO_COLORS.BLACK.value), ], base_signature, ) def __init__(self, formation, scodocParcour: ApcParcours = None): self.fromScodoc: ApcParcours = scodocParcour # None pour le tronc commun 'TC' self.etudiants = [] self.competences = {} self.annees = {} if scodocParcour is None: for ( scodocCompetence ) in formation.referentiel_competence.get_competences_tronc_commun(): self.competences[scodocCompetence.id] = CompetenceDesc(scodocCompetence) else: query = formation.query_competences_parcour(scodocParcour) if not query is None: for scodocCompetence in query.all(): self.competences[scodocCompetence.id] = CompetenceDesc( scodocCompetence ) for codeAnnee in listeAnnees: anneeDesc = AnneeDesc(codeAnnee) for competence_id, competence in self.competences.items(): anneeDesc.addNiveau(competence.getNiveaux(codeAnnee)) self.annees[codeAnnee] = anneeDesc def add_etudiant(self, etudiant): if not etudiant in self.etudiants: self.etudiants.append(etudiant) def getNiveauDesc(self, competence_id, niveau_id): return self.competences[competence_id].getNiveauDesc(niveau_id) def getData(self): data = [] for etudiant in self.etudiants: data.append(etudiant.getData()) return data def append_title_column(self, worksheet, cells, val1, val2, val3, val4): cells1, cells2, cells3, cells4 = cells cells1.append(worksheet.make_cell(val1)) cells2.append(worksheet.make_cell(val2)) cells3.append(worksheet.make_cell(val3)) cells4.append(worksheet.make_cell(val4)) def handle_description( self, ws: Worksheet, description: tuple, row: int, column: int ) -> int: title, content_list = description style = FMT.style(self.signature_header) ws.cell(row, column).value = title style.apply(ws.cell(row, column)) if content_list is None: ws.merge_cells( start_row=row, end_row=4, start_column=column, end_column=column ) column += 1 else: first = column for content in content_list: column = self.handle_description(ws, content, row + 1, column) if column - first > 1: ws.merge_cells( start_row=row, end_row=row, start_column=first, end_column=column - 1, ) # left_medium = FMT.compose( # self.signature_header, # [ # (FMT.BORDER_LEFT_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value), # (FMT.BORDER_LEFT_COLOR, SCO_COLORS.BLACK.value), # ], # ) # right_medium = FMT.compose( # self.signature_header, # [ # (FMT.BORDER_RIGHT_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value), # (FMT.BORDER_RIGHT_COLOR, SCO_COLORS.BLACK.value), # ], # ) # top_medium = FMT.compose( # self.signature_header, # [ # (FMT.BORDER_TOP_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value), # (FMT.BORDER_TOP_COLOR, SCO_COLORS.BLACK.value), # ], # ) # FMT.get_style(FMT.ALL, left_medium).apply(ws.cell(1, 1)) # FMT.get_style(FMT.ALL, top_medium).apply(ws.cell(1, 1)) # FMT.get_style(FMT.ALL, right_medium).apply(ws.cell(1, 1)) # FMT.get_style(FMT.ALL, left_medium).apply(ws.cell(2, 1)) # FMT.get_style(FMT.ALL, right_medium).apply(ws.cell(2, column - 1)) # FMT.get_style(FMT.ALL, right_medium).apply(ws.cell(3, column - 1)) # FMT.get_style(FMT.ALL, right_medium).apply(ws.cell(4, column - 1)) return column def generate_etudiant_header(self, ws: Worksheet) -> int: titles = ( "ETUDIANT", [ ("id", None), ("nip", None), ("Civ", None), ("nom", None), ("prenom", None), ("parcours", None), ("cursus", None), ( "absences", [ ("Tot.", None), ("Non", [("Just.", None)]), ], ), ], ) column = self.handle_description(ws, titles, 1, 1) return column def generate_header(self, ws: Worksheet): column: int = self.generate_etudiant_header(ws) for codeAnnee in listeAnnees: column = self.annees[codeAnnee].generate_header(ws, column, codeAnnee) def generate(self, workbook: ScoExcelBook): header = _Header() if self.fromScodoc: sheet_name = self.fromScodoc.code else: sheet_name = "TC" worksheet: ScoExcelSheet = workbook.create_sheet(sheet_name) self.generate_header(worksheet.ws)