294 lines
13 KiB
Python
294 lines
13 KiB
Python
import os
|
|
|
|
from django.conf import settings
|
|
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
|
|
|
|
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 = os.path.join(settings.MEDIA_ROOT, 'logo_EPC.png')
|
|
LOGO_ESNE = os.path.join(settings.MEDIA_ROOT, '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.periode_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', (7, 10), (7, 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)
|