############################################################################## # ScoDoc # Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved. # See LICENSE ############################################################################## """Génération bulletin BUT au format PDF standard """ from reportlab.platypus import Paragraph, Spacer from app.scodoc.sco_pdf import blue, cm, mm from app.scodoc import gen_tables from app.scodoc.sco_utils import fmt_note from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard class BulletinGeneratorStandardBUT(BulletinGeneratorStandard): """Génération du bulletin de BUT au format PDF. self.infos est le dict issu de BulletinBUT.bulletin_etud_complet() """ list_in_menu = False # spécialisation du BulletinGeneratorStandard, ne pas présenter à l'utilisateur scale_table_in_page = False small_fontsize = "8" def bul_table(self, format="html"): """Génère la table centrale du bulletin de notes Renvoie: - en HTML: une chaine - en PDF: une liste d'objets PLATYPUS (eg instance de Table). """ tables_infos = [ # ---- TABLE SYNTHESE UES self.but_table_synthese_ues(), ] if self.version != "short": tables_infos += [ # ---- TABLE RESSOURCES self.but_table_ressources(), # ---- TABLE SAE self.but_table_saes(), ] objects = [] for i, (col_keys, rows, pdf_style, col_widths) in enumerate(tables_infos): table = gen_tables.GenTable( rows=rows, columns_ids=col_keys, pdf_table_style=pdf_style, pdf_col_widths=[col_widths[k] for k in col_keys], preferences=self.preferences, html_class="notes_bulletin", html_class_ignore_default=True, html_with_td_classes=True, ) table_objects = table.gen(format=format) objects += table_objects # objects += [KeepInFrame(0, 0, table_objects, mode="shrink")] if i != 2: objects.append(Spacer(1, 6 * mm)) return objects def but_table_synthese_ues(self, title_bg=(182, 235, 255)): """La table de synthèse; pour chaque UE, liste des ressources et SAÉs avec leurs notes et leurs coefs. Renvoie: colkeys, P, pdf_style, colWidths - colkeys: nom des colonnes de la table (clés) - P : table (liste de dicts de chaines de caracteres) - pdf_style : commandes table Platypus - largeurs de colonnes pour PDF """ col_widths = { "titre": None, "moyenne": 2 * cm, "coef": 2 * cm, } title_bg = tuple(x / 255.0 for x in title_bg) nota_bene = "La moyenne des ressources et SAÉs dans une UE dépend des poids donnés aux évaluations." # elems pour générer table avec gen_table (liste de dicts) rows = [ # Ligne de titres { "titre": "Unités d'enseignement", "moyenne": Paragraph("Note/20"), "coef": "Coef.", "_coef_pdf": Paragraph("Coef."), "_css_row_class": "note_bold", "_pdf_row_markup": ["b"], "_pdf_style": [ ("BACKGROUND", (0, 0), (-1, 0), title_bg), # ("BOTTOMPADDING", (0, 0), (-1, 0), 7), ], }, { "titre": nota_bene, "_titre_pdf": Paragraph( f"{nota_bene}" ), "_titre_colspan": 3, "_pdf_style": [ ("BACKGROUND", (0, 0), (-1, 0), title_bg), ("BOTTOMPADDING", (0, 0), (-1, 0), 7), ( "LINEBELOW", (0, 0), (-1, 0), self.PDF_LINEWIDTH, blue, ), ], }, ] col_keys = ["titre", "coef", "moyenne"] # noms des colonnes à afficher for ue_acronym, ue in self.infos["ues"].items(): # 1er ligne titre UE moy_ue = ue.get("moyenne") t = { "titre": f"{ue_acronym} - {ue['titre']}", "moyenne": Paragraph( f"""{moy_ue.get("value", "-") if moy_ue is not None else "-"}""" ), "_css_row_class": "note_bold", "_pdf_row_markup": ["b"], "_pdf_style": [ ( "LINEABOVE", (0, 0), (-1, 0), self.PDF_LINEWIDTH, self.PDF_LINECOLOR, ), ("BACKGROUND", (0, 0), (-1, 0), title_bg), ("BOTTOMPADDING", (0, 0), (-1, 0), 7), ], } rows.append(t) # 2eme ligne titre UE (bonus/malus/ects) ects_txt = f'ECTS: {ue["ECTS"]["acquis"]:.3g} / {ue["ECTS"]["total"]:.3g}' t = { "titre": f"""Bonus: {ue['bonus']} - Malus: { ue["malus"]}""", "coef": ects_txt, "_coef_pdf": Paragraph(f"""{ects_txt}"""), "_coef_colspan": 2, # "_css_row_class": "", # "_pdf_row_markup": [""], "_pdf_style": [ ("BACKGROUND", (0, 0), (-1, 0), title_bg), ( "LINEBELOW", (0, 0), (-1, 0), self.PDF_LINEWIDTH, self.PDF_LINECOLOR, ), # cadre autour du bonus/malus ( "BOX", (0, 0), (0, 0), self.PDF_LINEWIDTH, (0.7, 0.7, 0.7), # gris clair ), ], } rows.append(t) # Liste chaque ressource puis SAE for mod_type in ("ressources", "saes"): for mod_code, mod in ue[mod_type].items(): t = { "titre": f"{mod_code} {self.infos[mod_type][mod_code]['titre']}", "moyenne": Paragraph( f'{mod["moyenne"]}' ), "coef": mod["coef"], "_coef_pdf": Paragraph( f"{mod['coef']}" ), "_pdf_style": [ ( "LINEBELOW", (0, 0), (-1, 0), self.PDF_LINEWIDTH, (0.7, 0.7, 0.7), # gris clair ) ], } rows.append(t) # Global pdf style commands: pdf_style = [ ("VALIGN", (0, 0), (-1, -1), "TOP"), ("BOX", (0, 0), (-1, -1), 0.4, blue), # ajoute cadre extérieur bleu: ] return col_keys, rows, pdf_style, col_widths def but_table_ressources(self): """La table de synthèse; pour chaque ressources, note et liste d'évaluations Renvoie: colkeys, P, pdf_style, colWidths """ return self.bul_table_modules( mod_type="ressources", title="Ressources", title_bg=(248, 200, 68) ) def but_table_saes(self): "table des SAEs" return self.bul_table_modules( mod_type="saes", title="Situations d'apprentissage et d'évaluation", title_bg=(198, 255, 171), ) def bul_table_modules(self, mod_type=None, title="", title_bg=(248, 200, 68)): """Table ressources ou SAEs - colkeys: nom des colonnes de la table (clés) - P : table (liste de dicts de chaines de caracteres) - pdf_style : commandes table Platypus - largeurs de colonnes pour PDF """ # UE à utiliser pour les poids (# colonne/UE) ue_acros = list(self.infos["ues"].keys()) # ['RT1.1', 'RT2.1', 'RT3.1'] # Colonnes à afficher: col_keys = ["titre"] + ue_acros + ["coef", "moyenne"] # Largeurs des colonnes: col_widths = { "titre": None, # "poids": None, "moyenne": 2 * cm, "coef": 2 * cm, } for ue_acro in ue_acros: col_widths[ue_acro] = 12 * mm # largeur col. poids title_bg = tuple(x / 255.0 for x in title_bg) # elems pour générer table avec gen_table (liste de dicts) # Ligne de titres t = { "titre": title, # "_titre_colspan": 1 + len(ue_acros), "moyenne": "Note/20", "coef": "Coef.", "_coef_pdf": Paragraph("Coef."), "_css_row_class": "note_bold", "_pdf_row_markup": ["b"], "_pdf_style": [ ("BACKGROUND", (0, 0), (-1, 0), title_bg), ("BOTTOMPADDING", (0, 0), (-1, 0), 7), ( "LINEBELOW", (0, 0), (-1, 0), self.PDF_LINEWIDTH, blue, ), ], } for ue_acro in ue_acros: t[ue_acro] = Paragraph( f"{ue_acro}" ) rows = [t] for mod_code, mod in self.infos[mod_type].items(): # 1er ligne titre module t = { "titre": f"{mod_code} - {mod['titre']}", "_titre_colspan": 2 + len(ue_acros), "_css_row_class": "note_bold", "_pdf_row_markup": ["b"], "_pdf_style": [ ( "LINEABOVE", (0, 0), (-1, 0), self.PDF_LINEWIDTH, self.PDF_LINECOLOR, ), ("BACKGROUND", (0, 0), (-1, 0), title_bg), ("BOTTOMPADDING", (0, 0), (-1, 0), 7), ], } rows.append(t) # Evaluations: for e in mod["evaluations"]: t = { "titre": f"{e['description']}", "moyenne": e["note"]["value"], "coef": e["coef"], "_coef_pdf": Paragraph( f"{e['coef']}" ), "_pdf_style": [ ( "LINEBELOW", (0, 0), (-1, 0), self.PDF_LINEWIDTH, (0.7, 0.7, 0.7), # gris clair ) ], } col_idx = 1 # 1ere col. poids for ue_acro in ue_acros: t[ue_acro] = Paragraph( f"""{e["poids"].get(ue_acro, "") or ""}""" ) t["_pdf_style"].append( ( "BOX", (col_idx, 0), (col_idx, 0), self.PDF_LINEWIDTH, (0.7, 0.7, 0.7), # gris clair ), ) col_idx += 1 rows.append(t) # Global pdf style commands: pdf_style = [ ("VALIGN", (0, 0), (-1, -1), "TOP"), ("BOX", (0, 0), (-1, -1), 0.4, blue), # ajoute cadre extérieur bleu: ] return col_keys, rows, pdf_style, col_widths