eds/cms/pdf.py
2017-11-01 16:10:31 +01:00

477 lines
22 KiB
Python

import os
from django.http.response import HttpResponse
from django.conf import settings
from reportlab.platypus import (SimpleDocTemplate, Spacer, Frame, Paragraph, Preformatted,
PageTemplate, NextPageTemplate, FrameBreak)
from reportlab.platypus import Table, TableStyle, Image
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 reportlab.pdfbase.pdfmetrics import stringWidth
from reportlab.lib.styles import getSampleStyleSheet
style_8_c = ps(name='CORPS', fontName='Helvetica', fontSize=6, alignment=TA_CENTER)
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, leftIndent=0.3*cm)
style_title = ps(name='CORPS', fontName='Helvetica', fontSize=12, alignment=TA_LEFT)
style_adress = ps(name='CORPS', fontName='Helvetica', fontSize=10, alignment=TA_LEFT, leftIndent=300)
class EpcBaseDocTemplate(SimpleDocTemplate):
def __init__(self, filename, titles=['',''], 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.logo_epc = os.path.join(settings.MEDIA_ROOT, 'logo_EPC.png')
self.logo_esne = os.path.join(settings.MEDIA_ROOT, 'logo_ESNE.png')
self.story = []
self.titles = titles
# Setting up the frames, frames are use for dynamic content not fixed page elements
first_page_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width + 1 * cm, self.height - 4 * cm,
id='small_table', showBoundary=0, leftPadding=0 * cm)
later_pages_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width + 1 * cm, self.height - 2 * cm,
id='large_table', showBoundary=0, leftPadding=0 * cm)
# Creating the page templates
first_page = PageTemplate(id='FirstPage', frames=[first_page_table_frame], onPage=self.header)
later_pages = PageTemplate(id='LaterPages', frames=[later_pages_table_frame])
self.addPageTemplates([first_page, later_pages])
# Tell Reportlab to use the other template on the later pages,
# by the default the first template that was added is used for the first page.
self.flowable = [NextPageTemplate(['*', 'LaterPages'])]
def header(self, canvas, doc):
canvas.saveState()
canvas.drawImage(self.logo_epc, doc.leftMargin, doc.height - 0.5 * cm, 5 * cm, 3 * cm, preserveAspectRatio=True)
canvas.drawImage(self.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, self.titles[0])
canvas.drawRightString(doc.width+doc.leftMargin, doc.height - 1.1* cm, self.titles[1])
canvas.line(doc.leftMargin, doc.height - 1.3 * cm, doc.width+doc.leftMargin, doc.height -1.3 * cm)
canvas.restoreState()
class MyESDocTemplate(SimpleDocTemplate):
def __init__(self, filename, titles=['',''], 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.titles = titles
self.page_width = (self.width + self.leftMargin * 2)
self.page_height = (self.height - self.bottomMargin * 2)
# Setting up the frames, frames are use for dynamic content not fixed page elements
first_page_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width+1*cm, self.height - 4*cm,
id='small_table', showBoundary=0, leftPadding=0*cm)
later_pages_table_frame = Frame(self.leftMargin, self.bottomMargin, self.width+1*cm, self.height-2*cm,
id='large_table', showBoundary=0, leftPadding=0*cm)
# Creating the page templates
first_page = PageTemplate(id='FirstPage', frames=[first_page_table_frame], onPage=self.on_first_page)
later_pages = PageTemplate(id='LaterPages', frames=[later_pages_table_frame], onPage=self.add_default_info)
self.addPageTemplates([first_page, later_pages])
# Tell Reportlab to use the other template on the later pages,
# by the default the first template that was added is used for the first page.
self.flowable =[NextPageTemplate(['*', 'LaterPages'])]
def on_first_page(self, canvas, doc):
canvas.saveState()
canvas.drawImage(settings.MEDIA_ROOT + 'logo_EPC.png', self.leftMargin, self.height-0.5*cm, 5 * cm, 3 * cm,
preserveAspectRatio=True)
canvas.drawImage(settings.MEDIA_ROOT + 'logo_ESNE.png', self.width-2*cm, self.height-0.5*cm, 5 * cm, 3 * cm,
preserveAspectRatio=True)
self._draw_title(canvas, self.height - 1*cm )
# self.add_default_info(canvas, doc)
canvas.restoreState()
def add_default_info(self, canvas, doc):
canvas.saveState()
self._draw_title(canvas, self.height+1*cm)
canvas.restoreState()
def _draw_title(self, canvas, height):
width = self.leftMargin + self.width
x = self.leftMargin
y = height
canvas.line(x, y, width, y)
y -= 15
canvas.drawString(x, y, self.titles[0])
canvas.drawRightString(width, y, self.titles[1])
y -= 8
canvas.line(x, y, width, y)
class MyDocTemplateES(SimpleDocTemplate):
def __init__(self, filename, title_left, title_right, 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)
if pageSize == A4:
page_size = A4
my_frame = Frame(2 * cm, 24 * cm, 17 * cm, 5 * cm, showBoundary=1)
else:
page_size = landscape(A4)
my_frame = Frame(2 * cm, 16 * cm, 25 * cm, 5 * cm, showBoundary=1)
self.flowable = list()
SimpleDocTemplate.__init__(self, filename, pagesize=page_size,
topMargin=0 * cm,
leftMargin=2 * cm,
rightMargin=2 * cm,
bottomMargin=0.5 * cm,
)
self.fileName = filename
width, height = page_size
self.textWidth = width - 2 * cm
self.canv = canvas.Canvas(filename, pagesize=page_size)
self.canv.drawImage(settings.MEDIA_ROOT + 'logo_EPC.png', 2 * cm, 17 * cm, 5 * cm, 5 * cm,
preserveAspectRatio=True)
self.canv.drawImage(settings.MEDIA_ROOT + 'logo_ESNE.png', 14 * cm, 25.5 * cm, 5 * cm, 5 * cm,
preserveAspectRatio=True)
string_width = stringWidth(title_right, 'Helvetica-Bold', 12)
self.canv.setFont('Helvetica-Bold', 12)
self.canv.line(2 * cm, 25.5 * cm, 19 * cm, 25.5 * cm)
self.canv.drawString(2 * cm, 25 * cm, title_left)
self.canv.drawString(self.textWidth-string_width, 25*cm, title_right)
self.canv.line(2 * cm, 24.6 * cm, 19 * cm, 24.6 * cm)
self.canv.setFont('Helvetica', 10)
my_frame.addFromList(self.flowable, self.canv)
"""
self.fileName = filename
self.canv = canvas.Canvas(filename, pagesize=A4)
im1 = Image(settings.MEDIA_ROOT + 'logo_EPC.png', width=170, height=80)
im2 = Image(settings.MEDIA_ROOT + 'logo_ESNE.png', width=170, height=80)
data = list()
data.append([im1, im2])
data.append([Spacer(0, 0.5 * cm)])
data.append([title_left, title_right])
t = Table(data, colWidths=[column_width] * 2, hAlign=TA_LEFT)
t.setStyle(
TableStyle(
[
('SIZE', (0, 0), (-1, -1), 9),
('FONT', (0, 0), (-1, -1), 'Helvetica-Bold'),
('ALIGN', (0, 0), (0, 0), 'LEFT'),
('ALIGN', (1, 0), (-1, -1), 'RIGHT'),
('LINEABOVE', (0, 2), (-1, 2), 0.5, colors.black),
('LINEBELOW', (0, -1), (-1, -1), 0.5, colors.black),
]
)
)
self.flowable.append(t)
"""
def beforePage(self):
# page number
self.canv.saveState()
self.canv.setFontSize(8)
self.canv.drawCentredString(self.pagesize[0] / 2, 0.5 * cm, "Page : " + str(self.canv.getPageNumber()))
self.canv.restoreState()
class ModulePdf(MyESDocTemplate):
def __init__(self, filename):
super().__init__(filename, ['Formation EDS', 'Module de formation'])
def preformatted_left(self, txt):
return Preformatted(txt, style_normal, maxLineLength=15)
def preformatted_right(self, txt):
return Preformatted(txt, style_normal, maxLineLength=97)
def produce(self, module):
str_comp = ''
for c in module.competence_set.all():
str_comp += '- {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_scom = ''
for c in module.competence_set.all():
for sc in c.souscompetence_set.all():
str_scom += '- {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_obj = ''
for c in module.objectif_set.all():
str_obj += '- {0}\n'.format(c.nom)
lines = module.contenu.split('\n')
str_con = ''
for l in lines:
str_con += '{0}\n'.format(l)
lines = module.evaluation.split('\n')
str_con = ''
for l in lines:
str_con += '{0}\n'.format(l)
# self.flowable.append(Spacer(0, 0.5 * cm))
self.story.append(Paragraph(module.__str__(), style_bold, ))
self.story.append(Spacer(0, 0.5 * cm))
d = [['Domaine', module.processus.domaine.__str__()],
['Processus', module.processus.__str__()],
['Situation emblématique', module.situation],
['Compétences visées', str_comp],
['Plus-value sur le CFC ASE', str_scom],
['Objectifs', str_obj],
['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()]
]
data = [
[self.preformatted_left('Domaine'), self.preformatted_right(module.processus.domaine.__str__())],
[self.preformatted_left('Processus'), self.preformatted_right(module.processus.__str__())],
[self.preformatted_left('Situation emblématique'), self.preformatted_right(module.situation)],
[self.preformatted_left('Compétences visées'), self.preformatted_right(str_comp)],
[self.preformatted_left('Plus-value sur le CFC ASE'), self.preformatted_right(str_scom)],
# [Preformatted_left('Ressources à acquérir'), Preformatted_right(str_res)],
[self.preformatted_left('Objectifs à atteindre'), self.preformatted_right(str_obj)],
[self.preformatted_left('Didactique'), self.preformatted_right(module.didactique)],
# [Preformatted_left('Contenu'), Preformatted_right(str_con)],
[self.preformatted_left('Evaluation'), self.preformatted_right(module.evaluation)],
[self.preformatted_left('Type'), self.preformatted_right('{0}, obligatoire'.format(module.type))],
[self.preformatted_left('Semestre'), self.preformatted_right('Sem. {0}'.format(module.semestre))],
[self.preformatted_left('Présentiel'),
self.preformatted_right('{0} heures'.format(module.periode_presentiel))],
[self.preformatted_left('Travail personnel'),
self.preformatted_right('{0} heures'.format(module.travail_perso))],
[self.preformatted_left('Responsable'),
self.preformatted_right(module.processus.domaine.responsable.descr_pdf())],
]
data = []
for foo in d:
data.append([self.preformatted_left(foo[0]), self.preformatted_right(foo[1])])
t = Table(data, colWidths=[3*cm, 13*cm])
t.hAlign = TA_CENTER
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, onFirstPage=self.header)
class PlanFormationPdf(EpcBaseDocTemplate):
def __init__(self, filename):
super().__init__(filename, ['Formation EDS', 'Plan de formation'], landscape(A4))
def formating(self, el1='', length=40):
el1 = '' if el1 == '' else el1.__str__()
return Preformatted(el1, style_normal, maxLineLength=length)
def produce(self, domain, process):
# my_frame = Frame(2*cm, 1*cm, 26*cm, 15*cm, showBoundary=1)
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_CENTER
self.story.append(t)
self.build(self.story, onFirstPage=self.header)
class PDFResponse(HttpResponse):
def __init__(self, filename, title='', portrait=True):
HttpResponse.__init__(self, content_type='application/pdf')
self['Content-Disposition'] = 'attachment; filename={0}'.format(filename)
self['Content-Type'] = 'charset=utf-8'
self.story = []
image = Image(settings.MEDIA_ROOT + '/media/header.png', width=400, height=80)
image.hAlign = TA_LEFT
self.story.append(image)
data = [['Filières EDS', title]]
if portrait:
t = Table(data, colWidths=[8*cm, 8*cm])
else:
t = Table(data, colWidths=[11*cm, 11*cm])
t.setStyle(TableStyle([
('ALIGN', (0, 0), (0, 0), 'LEFT'),
('ALIGN', (1, 0), (-1, -1), 'RIGHT'),
('LINEABOVE', (0, 0), (-1, -1), 0.5, colors.black),
('LINEBELOW', (0, -1), (-1, -1), 0.5, colors.black),
]))
t.hAlign = TA_LEFT
self.story.append(t)
class PeriodeFormationPdf(SimpleDocTemplate):
"""Imprime les heures de cours par semestre"""
def __init__(self, filename):
super().__init__(filename, pagesize=A4,
lefMargin=1.5 * cm, bottomMargin=1.5 * cm,
topMargin=1.5 * cm, rightMargin=1.5 * cm, showBoundary=1)
width = 8 * cm
height = 6.5 * cm
self.flowable = []
x = [self.leftMargin, 11.5*cm] * 3
y = [17,17, 10, 10, 3,3]
frames = [Frame(x[f], y[f]*cm, width=width, height=height, showBoundary=1, leftPadding=0, rightPadding=0) for f in range(6)]
# Page template
first_page = PageTemplate(id='FirstPage', frames=frames, onPage=self.on_first_page)
self.addPageTemplates(first_page)
self.titles = ['Filière EDS', 'Périodes de formation']
self.page_width = (self.width + self.leftMargin * 2)
self.page_height = (self.height - self.bottomMargin * 2)
def on_first_page(self, canvas, doc):
canvas.saveState()
logoEPC = os.path.join(settings.MEDIA_ROOT, 'logo_EPC.png')
canvas.drawImage(settings.MEDIA_ROOT + 'logo_EPC.png', doc.leftMargin, doc.height-0.5*cm, 5 * cm, 3 * cm,
preserveAspectRatio=True)
canvas.drawImage(settings.MEDIA_ROOT + 'logo_ESNE.png', doc.width-2*cm, doc.height-0.5*cm, 5 * cm, 3 * cm,
preserveAspectRatio=True)
height = doc.height - 1*cm
width = doc.leftMargin + doc.width
x = doc.leftMargin
y = height
canvas.line(x, y, width, y)
y -= 15
canvas.drawString(x, y, self.titles[0])
canvas.drawRightString(width, y, self.titles[1])
y -= 8
canvas.line(x, y, width, y)
canvas.restoreState()
def produce(self, context):
initial_pos_x = [2, 11.5]
initial_pos_y = [17, 17, 10, 10, 3, 3]
width = 7.5*cm
height = 6.5*cm
for sem in range(1,7):
x = initial_pos_x[(sem-1) % 2]*cm
y = initial_pos_y[sem-1]*cm
modules = context['sem{0}'.format(str(sem))]
total = context['tot{0}'.format(str(sem))]
# my_frame = Frame(x, y, width, height, showBoundary=1)
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)])
print(data)
t = Table(data, colWidths=[6*cm, 1*cm], spaceBefore=0.5*cm, spaceAfter=1*cm, hAlign=TA_LEFT)
t.setStyle(TableStyle([('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.flowable.append(t)
self.flowable.append(FrameBreak())
self.build(self.flowable)
def print_total(self, total):
self.canv.drawString(2*cm, 2*cm, 'Total de la formation: {0} heures'.format(total))