diff --git a/expenses_claim/forms.py b/expenses_claim/forms.py
index 0c40442..e616ab6 100644
--- a/expenses_claim/forms.py
+++ b/expenses_claim/forms.py
@@ -9,22 +9,23 @@ class ExpensesClaim(forms.Form):
name = forms.CharField(label='Nimi', max_length=100)
iban = forms.CharField(label='IBAN', max_length=100)
- amount = forms.DecimalField(label="Summa", decimal_places=2)
+ amount = forms.DecimalField(label='Summa', decimal_places=2)
def clean_iban(self):
"""Validate IBAN."""
- data = self.cleaned_data['iban']
+ orig_iban = self.cleaned_data['iban']
# Remove spaces.
- data = data.replace(" ", "")
+ cleaned_iban = orig_iban.replace(' ', '')
# Move first 4 symbols to the end of the string.
- data = data[4:] + data[0:4]
+ cleaned_iban = cleaned_iban[4:] + cleaned_iban[0:4]
LETTERS = {letter: str(index) for index,
letter in enumerate(ascii_uppercase, start=10)}
- data = data.upper()
+ cleaned_iban = cleaned_iban.upper()
# Replace all letters with numbers, so that A=10, B=11, ..., Z=35.
- data = [LETTERS[char] if char in LETTERS else char for char in data]
- data = ''.join(data)
- # If data modulo 97 != 1 the IBAN number is invalid.
- if int(data) % 97 != 1:
- raise forms.ValidationError("Invalid IBAN number!")
- return data
+ cleaned_iban = [LETTERS[char] if char in LETTERS
+ else char for char in cleaned_iban]
+ cleaned_iban = ''.join(cleaned_iban)
+ # If cleaned_iban modulo 97 != 1 the IBAN number is invalid.
+ if int(cleaned_iban) % 97 != 1:
+ raise forms.ValidationError('Invalid IBAN number!')
+ return orig_iban
diff --git a/expenses_claim/templates/claim.html b/expenses_claim/templates/claim.html
index 2afd7bb..63bc724 100644
--- a/expenses_claim/templates/claim.html
+++ b/expenses_claim/templates/claim.html
@@ -1,8 +1,8 @@
Dis is claim
diff --git a/expenses_claim/templates/claim2pdf.html b/expenses_claim/templates/claim2pdf.html
new file mode 100644
index 0000000..ae002b6
--- /dev/null
+++ b/expenses_claim/templates/claim2pdf.html
@@ -0,0 +1,20 @@
+
+
+
+ Raha-anomus
+
+
+ Raha-anomus
+
+
+ {{ name }}
+
+
+ {{ iban }}
+
+
+ {{ amount }}
+
+
+
+
diff --git a/expenses_claim/views.py b/expenses_claim/views.py
index d963dc9..cb34841 100644
--- a/expenses_claim/views.py
+++ b/expenses_claim/views.py
@@ -3,11 +3,13 @@
from django.shortcuts import render
from django.views.decorators.http import require_http_methods
from django.http import HttpResponse
-from webapp.utils import send_email
+from webapp.utils import send_email_with_attachment
+from django.template.loader import render_to_string
+from weasyprint import HTML
+import tempfile
from .forms import ExpensesClaim
-# Allow only GET or POST
@require_http_methods(["GET", "POST"])
def claim(request):
"""Render expenses claim form."""
@@ -15,11 +17,24 @@ def claim(request):
if request.method == 'POST':
form = ExpensesClaim(request.POST)
if form.is_valid():
- email = "leo.kivikunnas@gmail.com"
+ name = form.cleaned_data['name']
+ amount = form.cleaned_data['amount']
+ iban = form.cleaned_data['iban']
+ html_string = render_to_string('claim2pdf.html',
+ {'name': name, 'iban': iban,
+ 'amount': amount}).encode('UTF-8')
+ html = HTML(string=html_string)
+ attachment = html.write_pdf()
+ response = HttpResponse(
+ attachment, content_type='application/pdf;'
+ )
+ response['Content-Disposition'] = 'filename=claim.pdf'
+
+ email = "leo.kivikunnas@aalto.fi"
subject = "Test expenses claim"
- message = "Test"
- send_email(email, subject, message)
- return HttpResponse()
+ body = "Test"
+ send_email_with_attachment(email, subject, body, attachment)
+ return response
elif request.method == 'GET':
form = ExpensesClaim()
diff --git a/members/views/utils.py b/members/views/utils.py
index d6c1f8f..b908e31 100644
--- a/members/views/utils.py
+++ b/members/views/utils.py
@@ -145,6 +145,8 @@ def import_csv(request, *args, **kwargs):
return render(request, 'member_add_many_confirm.html', context)
+# TODO: There is also a similar wrapper in common utils why
+# not just use that?
def send_mail_wrapper(subject, message, email_to):
"""Send mail to default email."""
send_mail(subject,
diff --git a/requirements.txt b/requirements.txt
index a5764be..6616a93 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,39 +1,75 @@
+aiohttp==3.6.0
+async-timeout==3.0.1
+attrs==19.1.0
+Babel==2.7.0
+backports.csv==1.0.7
backports.shutil-get-terminal-size==1.0.0
+cairocffi==1.1.0
+CairoSVG==2.4.1
+cffi==1.12.3
+chardet==3.0.4
+coverage==4.3.4
+cssselect2==0.2.2
+dealer==2.0.5
decorator==4.0.9
+defusedxml==0.6.0
+diff-match-patch==20181111
Django==2.1.5
+django-app-namespace-template-loader==0.4.1
+django-auditlog==0.4.5
+django-autocomplete-light==3.2.10
+django-bootstrap3==8.2.3
+django-cors-headers==2.0.1
+django-filter==2.0.0
+django-import-export==0.7.0
+django-jsonfield==1.3.1
+django-modeltranslation==0.13b1
+django-nocaptcha-recaptcha==0.0.19
+django-nose==1.4.5
+django-phonenumber-field==1.3.0
+django-suit==0.2.26
+django-tables2==1.6.1
+djangorestframework==3.8.2
+djangorestframework-jwt==1.11.0
+et-xmlfile==1.0.1
+html5lib==1.0.1
+idna==2.8
ipython==4.2.0
ipython-genutils==0.1.0
-pexpect==4.1.0
-pickleshare==0.7.2
-ptyprocess==0.5.1
-pytz==2016.4
-simplegeneric==0.8.1
-traitlets==4.2.1
-Pillow==5.4.1
-requests==2.11.1
-django-nocaptcha-recaptcha==0.0.19
-django-cors-headers==2.0.1
-djangorestframework==3.8.2
-PyJWT==1.6.4
-djangorestframework-jwt==1.11.0
-coverage==4.3.4
-django-nose==1.4.5
+jdcal==1.4.1
+lml==0.0.9
+multidict==4.5.2
+nose==1.3.7
nose-exclude==0.5.0
-psycopg2-binary==2.7.6.1
-django-bootstrap3==8.2.3
-django-tables2==1.6.1
-pycodestyle==2.3.1
-dealer==2.0.5
-django-modeltranslation==0.13b1
-django-auditlog==0.4.5
-django-phonenumber-field==1.3.0
-django-autocomplete-light==3.2.10
-six==1.10.0
-django-suit==0.2.26
-telepot==12.3
-pyexcel==0.5.10
-pyexcel-xlsx==0.5.5
-django-import-export==0.7.0
+odfpy==1.4.0
openpyxl==2.4.11
-django-app-namespace-template-loader==0.4.1
-django-filter==2.0.0
+pexpect==4.1.0
+phonenumberslite==8.10.18
+pickleshare==0.7.2
+Pillow==5.4.1
+psycopg2-binary==2.7.6.1
+ptyprocess==0.5.1
+pycodestyle==2.3.1
+pycparser==2.19
+pyexcel==0.5.10
+pyexcel-io==0.5.20
+pyexcel-xlsx==0.5.5
+PyJWT==1.6.4
+Pyphen==0.9.5
+python-dateutil==2.6.0
+pytz==2016.4
+PyYAML==5.1.2
+requests==2.11.1
+simplegeneric==0.8.1
+six==1.10.0
+tablib==0.13.0
+telepot==12.3
+texttable==1.6.2
+tinycss2==1.0.2
+traitlets==4.2.1
+urllib3==1.25.3
+WeasyPrint==48
+webencodings==0.5.1
+xlrd==1.2.0
+xlwt==1.3.0
+yarl==1.3.0
diff --git a/webapp/utils.py b/webapp/utils.py
index 5e0cdd2..2aa850f 100644
--- a/webapp/utils.py
+++ b/webapp/utils.py
@@ -1,8 +1,7 @@
"""Webapp utils."""
from django.utils import timezone
-from django.core.mail import send_mail
-
+from django.core.mail import send_mail, EmailMessage
from datetime import timedelta
import logging
from django.conf import settings
@@ -27,3 +26,17 @@ def send_email(to, subject, body):
except Exception as ex:
logging.exception('Failed to send email.')
+
+
+def send_email_with_attachment(to, subject, body, attachment):
+ try:
+ email = EmailMessage(
+ subject, body, settings.DEFAULT_EMAIL_FROM, [to]
+ )
+ email.attach('raha.pdf', attachment, 'application/pdf;')
+ res = email.send()
+ if res == 0:
+ raise Exception('Failed to send email!')
+
+ except Exception as ex:
+ logging.exception('Failed to send email.')