From b8a353fa7ca0c714c69ab0ce4a6d82052f22e427 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sun, 3 Feb 2013 18:18:29 +0100 Subject: [PATCH] Added PDF view for the motions --- openslides/motion/pdf.py | 146 +++++++++++++++++++++++++++++++++++++ openslides/motion/urls.py | 10 +++ openslides/motion/views.py | 31 +++++++- 3 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 openslides/motion/pdf.py diff --git a/openslides/motion/pdf.py b/openslides/motion/pdf.py new file mode 100644 index 000000000..bf048649c --- /dev/null +++ b/openslides/motion/pdf.py @@ -0,0 +1,146 @@ +from reportlab.lib import colors +from reportlab.lib.units import cm +from reportlab.platypus import ( + SimpleDocTemplate, PageBreak, Paragraph, Spacer, Table, TableStyle) +from django.utils.translation import ugettext as _ + +from openslides.config.models import config +from openslides.utils.pdf import stylesheet + +from .models import Motion + + +def motions_to_pdf(pdf): + motions = Motion.objects.all() + all_motion_cover(pdf, motions) + for motion in motions: + pdf.append(PageBreak()) + motion_to_pdf(pdf, motion) + +def motion_to_pdf(pdf, motion): + pdf.append(Paragraph(_("Motion: %s") % motion.title, stylesheet['Heading1'])) + + motion_data = [] + + # submitter + cell1a = [] + cell1a.append(Spacer(0, 0.2 * cm)) + cell1a.append(Paragraph("%s:" % _("Submitter"), stylesheet['Heading4'])) + cell1b = [] + cell1b.append(Spacer(0, 0.2 * cm)) + cell1b.append(Paragraph(unicode(motion.submitter), stylesheet['Normal'])) + motion_data.append([cell1a, cell1b]) + + # TODO: choose this in workflow + if motion.state.edit_as_submitter: + # Cell for the signature + cell2a = [] + cell2b = [] + cell2a.append(Paragraph("%s:" % _("Signature"), stylesheet['Heading4'])) + cell2b.append(Paragraph(42 * "_", stylesheet['Signaturefield'])) + cell2b.append(Spacer(0, 0.1 * cm)) + cell2b.append(Spacer(0, 0.2 * cm)) + motion_data.append([cell2a, cell2b]) + + # supporters + if config['motion_min_supporters']: + cell3a = [] + cell3b = [] + cell3a.append(Paragraph("%s:" % _("Supporters"), stylesheet['Heading4'])) + supporters = motion.supporter.all() + for supporter in supporters: + cell3b.append(Paragraph(".  %s" % unicode(supporter), stylesheet['Signaturefield'])) + if motion.state.support: + for count in range(config['motion_min_supporters'] - supporters.count()): + cell3b.append(Paragraph(". " + 42 * "_",stylesheet['Signaturefield'])) + cell3b.append(Spacer(0, 0.2 * cm)) + motion_data.append([cell3a, cell3b]) + + ## # status + ## cell4a = [] + ## cell4b = [] + ## note = " ".join(motion.notes) + ## cell4a.append(Paragraph("%s:" % _("Status"), stylesheet['Heading4'])) + ## if note != "": + ## if motion.status == "pub": + ## cell4b.append(Paragraph(note, stylesheet['Normal'])) + ## else: + ## cell4b.append(Paragraph("%s | %s" % (motion.get_status_display(), note), stylesheet['Normal'])) + ## else: + ## cell4b.append(Paragraph("%s" % motion.get_status_display(), stylesheet['Normal'])) + ## data.append([cell4a, cell4b]) + + # Motion state + cell4a = [] + cell4b = [] + cell4a.append(Paragraph("%s:" % _("State"), stylesheet['Heading4'])) + cell4b.append(Paragraph(motion.state.name, stylesheet['Normal'])) + motion_data.append([cell4a, cell4b]) + + # Version number (aid) + if motion.versions.count() > 1: + cell5a = [] + cell5b = [] + cell5a.append(Paragraph("%s:" % _("Version"), stylesheet['Heading4'])) + cell5b.append(Paragraph("%s" % motion.version.version_number, stylesheet['Normal'])) + motion_data.append([cell5a, cell5b]) + + # voting results + polls = [] + for poll in motion.polls.all(): + if not poll.has_votes(): + continue + polls.append(poll) + + if polls: + cell6a = [] + cell6b = [] + cell6a.append(Paragraph("%s:" % _("Vote results"), stylesheet['Heading4'])) + ballotcounter = 0 + for poll in polls: + ballotcounter += 1 + option = poll.get_options()[0] + yes, no, abstain, invalid, votecast = ( + option['Yes'], option['No'], option['Abstain'], + poll.print_voteinvalid(), poll.print_votecast()) + + if len(polls) > 1: + cell6b.append(Paragraph("%s. %s" % (ballotcounter, _("Vote")), stylesheet['Bold'])) + cell6b.append(Paragraph( + "%s: %s
%s: %s
%s: %s
%s: %s
%s: %s" % + (_("Yes"), yes, _("No"), no, _("Abstention"), abstain, _("Invalid"), + invalid, _("Votes cast"), votecast), stylesheet['Normal'])) + cell6b.append(Spacer(0, 0.2 * cm)) + motion_data.append([cell6a, cell6b]) + + # Creating Table + table = Table(motion_data) + table._argW[0] = 4.5 * cm + table._argW[1] = 11 * cm + table.setStyle(TableStyle([('BOX', (0, 0), (-1, -1), 1, colors.black), + ('VALIGN', (0,0), (-1,-1), 'TOP')])) + pdf.append(table) + pdf.append(Spacer(0, 1 * cm)) + + pdf.append(Paragraph(motion.title, stylesheet['Heading3'])) + pdf.append(Paragraph(motion.text.replace('\r\n','
'), stylesheet['Paragraph'])) + if motion.reason: + pdf.append(Paragraph(_("Reason:"), stylesheet['Heading3'])) + pdf.append(Paragraph(motion.reason.replace('\r\n','
'), stylesheet['Paragraph'])) + return pdf + + +def all_motion_cover(pdf, motions): + pdf.append(Paragraph(config["motion_pdf_title"], stylesheet['Heading1'])) + + preamble = config["motion_pdf_preamble"] + if preamble: + pdf.append(Paragraph("%s" % preamble.replace('\r\n','
'), stylesheet['Paragraph'])) + + pdf.append(Spacer(0, 0.75 * cm)) + + if not motions: + pdf.append(Paragraph(_("No motions available."), stylesheet['Heading3'])) + else: + for motion in motions: + pdf.append(Paragraph(motion.title, stylesheet['Heading3'])) diff --git a/openslides/motion/urls.py b/openslides/motion/urls.py index 6331439b0..883b4c953 100644 --- a/openslides/motion/urls.py +++ b/openslides/motion/urls.py @@ -92,4 +92,14 @@ urlpatterns = patterns('openslides.motion.views', 'create_agenda_item', name='motion_create_agenda', ), + + url(r'^pdf/$', + 'motion_list_pdf', + name='motion_list_pdf', + ), + + url(r'^(?P\d+)/pdf/$', + 'motion_detail_pdf', + name='motion_detail_pdf', + ), ) diff --git a/openslides/motion/views.py b/openslides/motion/views.py index 3b13f9629..b562bf548 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -30,10 +30,12 @@ from openslides.projector.api import get_active_slide from openslides.projector.projector import Widget, SLIDE from openslides.config.models import config from openslides.agenda.models import Item + from .models import Motion, MotionSubmitter, MotionSupporter, MotionPoll, MotionVersion from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin, MotionCreateNewVersionMixin, ConfigForm) from .workflow import WorkflowError +from .pdf import motions_to_pdf, motion_to_pdf class MotionListView(ListView): @@ -274,7 +276,7 @@ class PollCreateView(SingleObjectMixin, RedirectView): def pre_redirect(self, request, *args, **kwargs): self.poll = self.object.create_poll() - self.object.write_log(ugettext_noop("Poll created"), user) + self.object.write_log(ugettext_noop("Poll created"), request.user) messages.success(request, _("New vote was successfully created.")) def get_redirect_url(self, **kwargs): @@ -370,6 +372,33 @@ class CreateAgendaItemView(SingleObjectMixin, RedirectView): create_agenda_item = CreateAgendaItemView.as_view() +class MotionPDFView(SingleObjectMixin, PDFView): + permission_required = 'motion.can_manage_motion' + model = Motion + top_space = 0 + print_all_motions = False + + def get(self, request, *args, **kwargs): + if not self.print_all_motions: + self.object = self.get_object() + return super(MotionPDFView, self).get(request, *args, **kwargs) + + def get_filename(self): + if self.print_all_motions: + return _("Motions") + else: + return _("Motion: %s") % unicode(self.object) + + def append_to_pdf(self, pdf): + if self.print_all_motions: + motions_to_pdf(pdf) + else: + motion_to_pdf(pdf, self.object) + +motion_list_pdf = MotionPDFView.as_view(print_all_motions=True) +motion_detail_pdf = MotionPDFView.as_view(print_all_motions=False) + + class Config(FormView): permission_required = 'config.can_manage_config' form_class = ConfigForm