from reportlab.platypus import (SimpleDocTemplate, Spacer, Frame, Paragraph, Preformatted, PageTemplate, NextPageTemplate, FrameBreak, Table, TableStyle) from reportlab.lib.pagesizes import A4, landscape from reportlab.lib.units import cm from reportlab.lib.enums import TA_LEFT, TA_CENTER from reportlab.lib import colors from reportlab.lib.colors import HexColor from reportlab.lib.styles import ParagraphStyle as ps from reportlab.pdfgen import canvas from django.contrib.staticfiles.finders import find style_normal = ps(name='CORPS', fontName='Helvetica', fontSize=9, alignment=TA_LEFT) style_bold = ps(name='CORPS', fontName='Helvetica-Bold', fontSize=10, alignment=TA_LEFT) LOGO_EPC = find('img/logo_EPC.png') LOGO_ESNE = find('img/logo_ESNE.png') FILIERE = 'Formation EDS' class NumberedCanvas(canvas.Canvas): """ Page number and pages counter """ def __init__(self, *args, **kwargs): canvas.Canvas.__init__(self, *args, **kwargs) self._saved_page_states = [] def showPage(self): self._saved_page_states.append(dict(self.__dict__)) self._startPage() def save(self): """add page info to each page (page x of y)""" num_pages = len(self._saved_page_states) for state in self._saved_page_states: self.__dict__.update(state) self.draw_page_number(num_pages) canvas.Canvas.showPage(self) canvas.Canvas.save(self) def draw_page_number(self, page_count): self.setFont("Helvetica", 7) self.drawString(self._pagesize[0] / 2, 1 * cm, "Page {0} de {1}".format(self._pageNumber, page_count)) class EpcBaseDocTemplate(SimpleDocTemplate): def __init__(self, filename, title='', pagesize=A4): super().__init__(filename, pagesize=pagesize, _pageBreakQuick=0, lefMargin=1.5 * cm, bottomMargin=1.5 * cm, topMargin=1.5 * cm, rightMargin=1.5 * cm) self.story = [] self.title = title def header(self, canvas, doc): canvas.saveState() canvas.drawImage(LOGO_EPC, doc.leftMargin, doc.height - 0.5 * cm, 5 * cm, 3 * cm, preserveAspectRatio=True) canvas.drawImage(LOGO_ESNE, doc.width - 2 * cm, doc.height - 0.5 * cm, 5 * cm, 3 * cm, preserveAspectRatio=True) canvas.line(doc.leftMargin, doc.height - 0.5 * cm, doc.width + doc.leftMargin, doc.height - 0.5 * cm) canvas.drawString(doc.leftMargin, doc.height - 1.1 * cm, FILIERE) canvas.drawRightString(doc.width + doc.leftMargin, doc.height - 1.1 * cm, self.title) canvas.line(doc.leftMargin, doc.height - 1.3 * cm, doc.width + doc.leftMargin, doc.height - 1.3 * cm) canvas.restoreState() def later_header(self, canvas, doc): canvas.saveState() canvas.line(doc.leftMargin, doc.height + 1 * cm, doc.width + doc.leftMargin, doc.height + 1 * cm) canvas.drawString(doc.leftMargin, doc.height + 0.5 * cm, FILIERE) canvas.drawRightString(doc.width + doc.leftMargin, doc.height + 0.5 * cm, self.title) canvas.line(doc.leftMargin, doc.height + 0.2 * cm, doc.width + doc.leftMargin, doc.height + 0.2 * cm) canvas.restoreState() def setNormalTemplatePage(self): first_page_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width + 1 * cm, self.height - 4 * cm, id='first_table', showBoundary=0, leftPadding=0 * cm) later_pages_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width + 1 * cm, self.height - 2 * cm, id='later_table', showBoundary=0, leftPadding=0 * cm) # Page template first_page = PageTemplate(id='FirstPage', frames=[first_page_table_frame], onPage=self.header) later_pages = PageTemplate(id='LaterPages', frames=[later_pages_table_frame], onPage=self.later_header) self.addPageTemplates([first_page, later_pages]) self.story = [NextPageTemplate(['*', 'LaterPages'])] def setSixSemestreTemplatePage(self): frame_size = (8 * cm, 6.5 * cm,) w, h = frame_size x = [self.leftMargin, 12 * cm] * 3 y = [17 * cm, 17 * cm, 10 * cm, 10 * cm, 3 * cm, 3 * cm] frames = [Frame(x[f], y[f], width=w, height=h, showBoundary=0, leftPadding=0) for f in range(6)] # Frame for total periods frames.append(Frame(self.leftMargin, self.bottomMargin, self.width, 1.5 * cm, leftPadding=0)) # Page template frame_page = PageTemplate(id='FirstPage', frames=frames, onPage=self.header) self.addPageTemplates(frame_page) class ModuleDescriptionPdf(EpcBaseDocTemplate): """ PDF for module description """ def __init__(self, filename): super().__init__(filename, 'Module de formation', A4) self.setNormalTemplatePage() def produce(self, module): str_competence = '' for c in module.competence_set.all(): str_competence += '- {0} ({1})\n'.format(c.nom, c.code) """ if self.request.user.is_authenticated: for sc in c.souscompetence_set.all(): str_comp += ' -- {0}\n'.format(sc.nom) """ str_sous_competence = '' for c in module.competence_set.all(): for sc in c.souscompetence_set.all(): str_sous_competence += '- {0} (voir {1})\n'.format(sc.nom, c.code) str_res = '' for c in module.ressource_set.all(): str_res += '- {0}\n'.format(c.nom) str_objectif = '' for c in module.objectif_set.all(): str_objectif += '- {0}\n'.format(c.nom) self.story.append(Paragraph(module.__str__(), style_bold)) self.story.append(Spacer(0, 0.5 * cm)) data = [ ['Domaine', module.processus.domaine.__str__()], ['Processus', module.processus.__str__()], ['Situation emblématique', module.situation], ['Compétences visées', str_competence], ['Plus-value sur le CFC ASE', str_sous_competence], ['Objectifs', str_objectif], ['Didactique', module.didactique], ['Evaluation', module.evaluation], ['Type', '{0}, obligatoire'.format(module.type)], ['Semestre', 'Sem. {0}'.format(module.semestre)], ['Présentiel', '{0} heures'.format(module.total_presentiel)], ['Travail personnel', '{0} heures'.format(module.travail_perso)], ['Responsable', module.processus.domaine.responsable.descr_pdf()] ] formated_data = [] for foo in data: formated_data.append( [Preformatted(foo[0], style_normal, maxLineLength=15), Preformatted(foo[1], style_normal, maxLineLength=97), ] ) t = Table(formated_data, colWidths=[4 * cm, 13 * cm]) t.hAlign = TA_LEFT t.setStyle( TableStyle( [ ('SIZE', (0, 0), (-1, -1), 7), ('ALIGN', (0, 0), (-1, -1), 'LEFT'), ('VALIGN', (0, 0), (-1, -1), 'TOP'), ('LEFTPADDING', (0, 0), (-1, -1), 0), ] ) ) self.story.append(t) self.build(self.story, canvasmaker=NumberedCanvas) class FormationPlanPdf(EpcBaseDocTemplate): """ PDF for formation plan """ def __init__(self, filename): super().__init__(filename, 'Plan de formation', landscape(A4)) self.setNormalTemplatePage() def formating(self, el1='', length=40): el1 = '' if el1 == '' else el1.__str__() return Preformatted(el1, style_normal, maxLineLength=length) def produce(self, domain, process): data = [ ['Domaines', 'Processus', 'Sem1', 'Sem2', 'Sem3', 'Sem4', 'Sem5', 'Sem6'], [self.formating(domain[0]), self.formating(process[0], 60), 'M01', '', '', '', '', ''], [self.formating(''), self.formating('', 60), 'M02', '', '', '', '', ''], [self.formating(''), self.formating(process[1], 60), '', '', '', 'M03', '', ''], [self.formating(''), self.formating('', 60), '', 'M04', '', '', '', ''], [self.formating(domain[1]), self.formating(process[2], 60), 'M05', '', 'M06', '', '', ''], [self.formating(''), self.formating(process[3], 60), '', '', '', '', 'M07', 'M09'], [self.formating(''), self.formating('', 60), '', '', '', '', 'M08', ''], [self.formating(domain[2]), self.formating(process[4], 60), '', '', 'M10', '', 'M12'], [self.formating(''), self.formating(process[5], 60), '', '', 'M11', '', ''], [self.formating(domain[3]), self.formating(process[6], 60), '', '', 'M13', '', 'M14', ''], [self.formating(domain[4]), self.formating(process[7], 60), 'M15', '', '', '', '', ''], [self.formating(domain[5]), self.formating(process[8], 60), 'M16_1', '', 'M16_2', '', 'M16_3', ''], [self.formating(domain[6]), self.formating(process[9], 60), 'M17_1', '', 'M17_2', '', 'M17_3', ''], [self.formating(domain[7]), self.formating(process[10], 60), 'Macc', '', '', '', '', ''], ] t = Table(data, colWidths=[7 * cm, 9 * cm, 1.5 * cm, 1.5 * cm, 1.5 * cm, 1.5 * cm, 1.5 * cm, 1.5 * cm], spaceBefore=0.5 * cm, spaceAfter=1 * cm ) t.setStyle(TableStyle([ ('SIZE', (0, 0), (-1, -1), 8), ('FONT', (0, 0), (-1, 0), 'Helvetica-Bold'), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), ('ALIGN', (2, 0), (-1, -1), 'CENTER'), ('GRID', (0, 0), (-1, -1), 0.25, colors.black), # Domaine 1 ('SPAN', (0, 1), (0, 4)), ('SPAN', (1, 1), (1, 2)), ('SPAN', (1, 3), (1, 4)), ('BACKGROUND', (0, 1), (1, 4), colors.orange), ('BACKGROUND', (2, 1), (2, 2), colors.orange), ('BACKGROUND', (5, 3), (5, 3), colors.orange), ('BACKGROUND', (3, 4), (3, 4), colors.orange), # Domaine 2 ('SPAN', (0, 5), (0, 7)), ('BACKGROUND', (0, 5), (1, 7), colors.red), ('BACKGROUND', (2, 5), (2, 5), colors.red), ('BACKGROUND', (4, 5), (4, 5), colors.red), ('BACKGROUND', (6, 6), (6, 6), colors.red), ('BACKGROUND', (7, 6), (7, 6), colors.red), ('BACKGROUND', (6, 7), (6, 7), colors.red), # Domaine 3 ('SPAN', (0, 8), (0, 9)), ('SPAN', (1, 6), (1, 7)), ('SPAN', (4, 8), (5, 8)), ('SPAN', (4, 9), (5, 9)), ('BACKGROUND', (0, 8), (1, 9), colors.pink), ('BACKGROUND', (4, 8), (6, 8), colors.pink), ('BACKGROUND', (4, 9), (5, 9), colors.pink), # Domaine 4 ('BACKGROUND', (0, 10), (1, 10), HexColor('#AD7FA8')), ('BACKGROUND', (4, 10), (4, 10), HexColor('#AD7FA8')), ('BACKGROUND', (6, 10), (6, 10), HexColor('#AD7FA8')), # Domaine 5 ('SPAN', (2, 11), (-1, 11)), ('BACKGROUND', (0, 11), (-1, 11), HexColor('#729FCF')), # Domaine 6 ('SPAN', (2, 12), (3, 12)), ('SPAN', (4, 12), (5, 12)), ('SPAN', (6, 12), (7, 12)), ('BACKGROUND', (0, 12), (-1, 12), colors.lightgreen), # Domaine 7 ('SPAN', (2, 13), (3, 13)), ('SPAN', (4, 13), (5, 13)), ('SPAN', (6, 13), (7, 13)), ('BACKGROUND', (0, 13), (-1, 13), colors.white), # Domaine 8 ('SPAN', (2, 14), (-1, 14)), ('BACKGROUND', (0, 14), (-1, 14), colors.lightgrey), ])) t.hAlign = TA_LEFT self.story.append(t) self.build(self.story, canvasmaker=NumberedCanvas) class PeriodSemesterPdf(EpcBaseDocTemplate): """ PDF for periods during semesters """ def __init__(self, filename): super().__init__(filename, 'Périodes de formation', A4) self.setSixSemestreTemplatePage() def produce(self, context): for sem in range(1, 7): modules = context['sem{0}'.format(str(sem))] total = context['tot{0}'.format(str(sem))] data = [['Semestre {0}'.format(sem), '{0} h.'.format(total)]] for line in modules: value = getattr(line, 'sem{0}'.format(sem)) data.append([line.nom, '{0} h.'.format(value)]) t = Table(data, colWidths=[6.5 * cm, 1 * cm], spaceBefore=0.5 * cm, spaceAfter=1 * cm, hAlign=TA_LEFT, style=[ ('ALIGN', (0, 0), (0, 0), 'LEFT'), ('ALIGN', (1, 0), (-1, -1), 'RIGHT'), ('LINEBELOW', (0, 0), (1, 0), 1, colors.black), ('SIZE', (0, 0), (-1, -1), 9), ('FONT', (0, 0), (-1, 0), 'Helvetica-Bold'), ] ) self.story.append(t) self.story.append(FrameBreak()) self.story.append(Paragraph('Total de la formation: {0} heures'.format(context['tot']), style_bold)) self.build(self.story, canvasmaker=NumberedCanvas)