Add API route to generate member's application PDF forms

This commit is contained in:
Tanner Collin 2020-01-26 08:29:14 +00:00
parent e24de87557
commit 0c1f82a3c7
5 changed files with 69 additions and 3 deletions

View File

@ -1,9 +1,13 @@
from rest_framework.exceptions import ValidationError
import datetime import datetime
import io
from rest_framework.exceptions import ValidationError
from dateutil import relativedelta from dateutil import relativedelta
from uuid import uuid4 from uuid import uuid4
from PIL import Image from PIL import Image
from bleach.sanitizer import Cleaner from bleach.sanitizer import Cleaner
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from django.db.models import Sum from django.db.models import Sum
@ -239,3 +243,42 @@ def link_old_member(data, user):
for t in training: for t in training:
t.user = user t.user = user
t.save() t.save()
BLANK_FORM = 'misc/blank_member_form.pdf'
def generate_application_pdf(member):
packet = io.BytesIO()
can = canvas.Canvas(packet, pagesize=letter)
can.drawRightString(580, 770, '{} {} ({})'.format(
member['first_name'],
member['last_name'],
member['id'],
))
can.drawString(34, 683, member['first_name'])
can.drawString(218, 683, member['last_name'])
can.drawString(403, 683, member['preferred_name'])
can.drawString(34, 654, member['street_address'])
can.drawString(275, 654, member['city'])
can.drawString(459, 654, member['postal_code'])
can.drawString(34, 626, member['email'])
can.drawString(332, 626, member['phone'])
can.drawString(34, 570, member['emergency_contact_name'])
can.drawString(332, 570, member['emergency_contact_phone'])
can.save()
packet.seek(0)
new_pdf = PdfFileReader(packet)
existing_pdf = PdfFileReader(open(BLANK_FORM, 'rb'))
output = PdfFileWriter()
page = existing_pdf.getPage(0)
page.mergePage(new_pdf.getPage(0))
output.addPage(page)
page = existing_pdf.getPage(1)
output.addPage(page)
page = existing_pdf.getPage(2)
output.addPage(page)
outputStream = io.BytesIO()
output.write(outputStream)
return outputStream

View File

@ -1,6 +1,8 @@
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.db.models import Max from django.db.models import Max
from django.http import HttpResponse
from django.core.files.base import File
from rest_framework import viewsets, views, mixins, generics, exceptions from rest_framework import viewsets, views, mixins, generics, exceptions
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
@ -110,7 +112,7 @@ class MemberViewSet(Base, Retrieve, Update):
def pause(self, request, pk=None): def pause(self, request, pk=None):
if not is_admin_director(self.request.user): if not is_admin_director(self.request.user):
raise exceptions.PermissionDenied() raise exceptions.PermissionDenied()
member = get_object_or_404(self.queryset, pk=pk) member = self.get_object()
member.paused_date = datetime.date.today() member.paused_date = datetime.date.today()
member.save() member.save()
return Response(200) return Response(200)
@ -119,13 +121,20 @@ class MemberViewSet(Base, Retrieve, Update):
def unpause(self, request, pk=None): def unpause(self, request, pk=None):
if not is_admin_director(self.request.user): if not is_admin_director(self.request.user):
raise exceptions.PermissionDenied() raise exceptions.PermissionDenied()
member = get_object_or_404(self.queryset, pk=pk) member = self.get_object()
member.current_start_date = datetime.date.today() member.current_start_date = datetime.date.today()
member.paused_date = None member.paused_date = None
member.save() member.save()
utils.tally_membership_months(member) utils.tally_membership_months(member)
return Response(200) return Response(200)
@action(detail=True)
def forms(self, request, pk=None):
member = self.get_object()
serializer = self.get_serializer(member)
form = utils.generate_application_pdf(serializer.data)
return HttpResponse(File(form), content_type='application/pdf')
class CardViewSet(Base, Create, Retrieve, Update, Destroy): class CardViewSet(Base, Create, Retrieve, Update, Destroy):
permission_classes = [AllowMetadata | IsAuthenticated, IsObjOwnerOrAdmin] permission_classes = [AllowMetadata | IsAuthenticated, IsObjOwnerOrAdmin]

View File

@ -343,6 +343,18 @@ Pausing / Unpausing Member
:status 200: :status 200:
Member PDF Forms
++++++++++++++++
.. http:get:: /members/(id)/forms/
Generate member's application PDF forms. Users can only view their own,
admins can view anyone's.
:param id:
:requestheader Authorization: ``Token <token>``
Search Search
------ ------

Binary file not shown.

View File

@ -23,10 +23,12 @@ Pillow==7.0.0
pycparser==2.19 pycparser==2.19
Pygments==2.5.2 Pygments==2.5.2
pyparsing==2.4.6 pyparsing==2.4.6
PyPDF2==1.26.0
python-dateutil==2.8.1 python-dateutil==2.8.1
python-Levenshtein==0.12.0 python-Levenshtein==0.12.0
python3-openid==3.1.0 python3-openid==3.1.0
pytz==2019.3 pytz==2019.3
reportlab==3.5.34
requests==2.22.0 requests==2.22.0
requests-oauthlib==1.3.0 requests-oauthlib==1.3.0
six==1.13.0 six==1.13.0