Commit ff5a05a0 authored by Michal Čihař's avatar Michal Čihař

Add support for invoice downloads

Signed-off-by: default avatarMichal Čihař <michal@cihar.com>
parent e86cb9a7
......@@ -24,6 +24,7 @@ include docs/_ext/*.py
include docs/_static/*.png
include docs/_templates/*.html
recursive-include examples *
include weblate/billing/test-data/*
include weblate/trans/tests/data/*
include weblate/trans/widget-images/*.png
include weblate/lang/plurals.txt
......
......@@ -234,6 +234,11 @@ DEFAULT_TRANSLATION_PROPAGATION = getvalue(
'DEFAULT_TRANSLATION_PROPAGATION', True
)
# Billing
INVOICE_PATH = getvalue(
'INVOICE_PATH', ''
)
# Obsolete configs, needed for data migration
GIT_ROOT = getvalue('GIT_ROOT', os.path.join(BASE_DIR, 'repos'))
WHOOSH_INDEX = getvalue('WHOOSH_INDEX', os.path.join(BASE_DIR, 'whoosh-index'))
......@@ -170,6 +170,12 @@ class Invoice(models.Model):
def __str__(self):
return '{0} - {1}: {2}'.format(self.start, self.end, self.billing)
@property
def filename(self):
if self.ref:
return '{0}.pdf'.format(self.ref)
return None
def clean(self):
if self.end is None or self.start is None:
return
......
......@@ -19,6 +19,7 @@
#
from datetime import timedelta
import os.path
from six import StringIO
......@@ -26,15 +27,27 @@ from django.test import TestCase
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core.management import call_command
from django.core.urlresolvers import reverse
from django.utils import timezone
from weblate.billing.models import Plan, Billing, Invoice
from weblate.trans.models import Project
from weblate.trans.tests import OverrideSettings
TEST_DATA = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'test-data'
)
class BillingTest(TestCase):
def setUp(self):
self.user = User.objects.create(username='bill')
self.user = User.objects.create_user(
username='bill',
password='kill',
email='noreply@example.net'
)
self.plan = Plan.objects.create(name='test', limit_projects=1, price=0)
self.billing = Billing.objects.create(user=self.user, plan=self.plan)
self.invoice = Invoice.objects.create(
......@@ -42,6 +55,7 @@ class BillingTest(TestCase):
start=timezone.now().date() - timedelta(days=2),
end=timezone.now().date() + timedelta(days=2),
payment=10,
ref='00000',
)
self.projectnum = 0
......@@ -128,3 +142,42 @@ class BillingTest(TestCase):
# Validation of existing
self.invoice.clean()
@OverrideSettings(INVOICE_PATH=TEST_DATA)
def test_download(self):
# Unauthenticated
response = self.client.get(
reverse('invoice-download', kwargs={'pk': self.invoice.pk})
)
self.assertEquals(302, response.status_code)
# Not owner
User.objects.create_user(username='foo', password='bar')
self.client.login(username='foo', password='bar')
response = self.client.get(
reverse('invoice-download', kwargs={'pk': self.invoice.pk})
)
self.assertEquals(403, response.status_code)
# Owner
self.client.login(username='bill', password='kill')
response = self.client.get(
reverse('invoice-download', kwargs={'pk': self.invoice.pk})
)
self.assertContains(response, 'PDF-INVOICE')
# Invoice without file
invoice = Invoice.objects.create(
billing=self.billing,
start=timezone.now().date() - timedelta(days=2),
end=timezone.now().date() + timedelta(days=2),
payment=10,
)
response = self.client.get(
reverse('invoice-download', kwargs={'pk': invoice.pk})
)
self.assertEquals(404, response.status_code)
# Invoice with non existing file
invoice.ref = 'NON'
invoice.save()
response = self.client.get(
reverse('invoice-download', kwargs={'pk': invoice.pk})
)
self.assertEquals(404, response.status_code)
......@@ -17,3 +17,45 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os.path
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
from django.http import HttpResponse, Http404
from weblate import appsettings
from weblate.billing.models import Invoice
@login_required
def download_invoice(request, pk):
"""Download invoice PDF"""
invoice = get_object_or_404(Invoice, pk=pk)
if not invoice.ref:
raise Http404('No reference!')
if invoice.billing.user != request.user:
raise PermissionDenied('Not an owner!')
filename = invoice.filename
path = os.path.join(appsettings.INVOICE_PATH, filename)
if not os.path.exists(path):
raise Http404('File {0} does not exist!'.format(filename))
with open(path, 'rb') as handle:
data = handle.read()
response = HttpResponse(
data,
content_type='application/pdf'
)
response['Content-Disposition'] = 'attachment; filename={0}'.format(
filename
)
response['Content-Length'] = len(data)
return response
......@@ -379,7 +379,13 @@
<tr>
<td>{{ invoice.start|date:"SHORT_DATE_FORMAT" }} - {{ invoice.end|date:"SHORT_DATE_FORMAT" }}</td>
<td>{{ invoice.payment }} {{ invoice.get_currency_display }}</td>
<td>{% trans "Not available" %}</td>
<td>
{% if invoice.ref %}
<a href="{% url 'invoice-download' pk=invoice.pk %}">{{ invoice.filename }}</a>
{% else %}
{% trans "Not available" %}
{% endif %}
</td>
</tr>
{% empty %}
<tr><td colspan="3">{% trans "No invoices found!" %}</td/></tr>
......
......@@ -19,6 +19,7 @@
#
from django.conf.urls import include, url
from django.conf import settings
from django.contrib import admin
from django.views.generic import RedirectView
import django.contrib.sitemaps.views
......@@ -30,6 +31,7 @@ from weblate.trans.feeds import (
)
from weblate.trans.views.changes import ChangesView, ChangesCSVView
import weblate.accounts.views
import weblate.billing.views
import weblate.lang.views
import weblate.trans.admin_views
import weblate.trans.views.acl
......@@ -837,3 +839,12 @@ urlpatterns = [
name="search"
),
]
if 'weblate.billing' in settings.INSTALLED_APPS:
urlpatterns += [
url(
r'^invoice/(?P<pk>[0-9]+)/download/$',
weblate.billing.views.download_invoice,
name='invoice-download',
),
]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment