diff --git a/musician/api.py b/musician/api.py index 78964bd..8b4139c 100644 --- a/musician/api.py +++ b/musician/api.py @@ -28,6 +28,7 @@ API_PATHS = { # other 'bill-list': 'bills/', + 'bill-document': 'bills/{pk}/document/', 'payment-source-list': 'payment-sources/', } @@ -59,7 +60,7 @@ class Orchestra(object): return response.json().get("token", None) - def request(self, verb, resource=None, querystring=None, url=None, raise_exception=True): + def request(self, verb, resource=None, url=None, render_as="json", querystring=None, raise_exception=True): assert verb in ["HEAD", "GET", "POST", "PATCH", "PUT", "DELETE"] if resource is not None: url = self.build_absolute_uri(resource) @@ -77,7 +78,10 @@ class Orchestra(object): response.raise_for_status() status = response.status_code - output = response.json() + if render_as == "json": + output = response.json() + else: + output = response.content return status, output @@ -94,6 +98,15 @@ class Orchestra(object): raise PermissionError("Cannot retrieve profile of an anonymous user.") return UserAccount.new_from_json(output[0]) + def retrieve_bill_document(self, pk): + path = API_PATHS.get('bill-document').format_map({'pk': pk}) + + url = urllib.parse.urljoin(self.base_url, path) + status, bill_pdf = self.request("GET", render_as="html", url=url, raise_exception=False) + if status == 404: + raise Http404(_("No domain found matching the query")) + return bill_pdf + def retrieve_domain(self, pk): path = API_PATHS.get('domain-detail').format_map({'pk': pk}) diff --git a/musician/models.py b/musician/models.py index b0faab8..db3367b 100644 --- a/musician/models.py +++ b/musician/models.py @@ -51,6 +51,7 @@ class OrchestraModel: class Bill(OrchestraModel): api_name = 'bill' param_defaults = { + "id": None, "number": "1", "type": "INVOICE", "total": 0.0, @@ -60,12 +61,6 @@ class Bill(OrchestraModel): "comments": "", } - def pdf_url(self): - # TODO (@slamora) create a view that exposes & downloads backend PDF - import urllib.parse - bill_url = self._json.get('url') - return urllib.parse.urljoin(bill_url, 'document/') - class BillingContact(OrchestraModel): param_defaults = { diff --git a/musician/templates/musician/billing.html b/musician/templates/musician/billing.html index c374dc0..46d1396 100644 --- a/musician/templates/musician/billing.html +++ b/musician/templates/musician/billing.html @@ -30,7 +30,7 @@ {{ bill.created_on }} {{ bill.type }} {{ bill.total|floatformat:2|localize }}€ - + {% endfor %} diff --git a/musician/urls.py b/musician/urls.py index 6bae570..9139f35 100644 --- a/musician/urls.py +++ b/musician/urls.py @@ -16,7 +16,8 @@ urlpatterns = [ path('auth/logout/', views.LogoutView.as_view(), name='logout'), path('dashboard/', views.DashboardView.as_view(), name='dashboard'), path('domains//', views.DomainDetailView.as_view(), name='domain-detail'), - path('billing/', views.BillingView.as_view(), name='billing'), + path('bills/', views.BillingView.as_view(), name='billing'), + path('bills//download/', views.BillDownloadView.as_view(), name='bill-download'), path('profile/', views.ProfileView.as_view(), name='profile'), path('mails/', views.MailView.as_view(), name='mails'), path('mailing-lists/', views.MailingListsView.as_view(), name='mailing-lists'), diff --git a/musician/views.py b/musician/views.py index b0271b1..7a8a2d1 100644 --- a/musician/views.py +++ b/musician/views.py @@ -1,11 +1,12 @@ from itertools import groupby from django.core.exceptions import ImproperlyConfigured -from django.http import HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render from django.urls import reverse_lazy from django.utils.http import is_safe_url from django.utils.translation import gettext_lazy as _ +from django.views import View from django.views.generic.base import RedirectView, TemplateView from django.views.generic.detail import DetailView from django.views.generic.edit import FormView @@ -133,6 +134,14 @@ class BillingView(ServiceListView): template_name = "musician/billing.html" +class BillDownloadView(CustomContextMixin, UserTokenRequiredMixin, View): + def get(self, request, *args, **kwargs): + pk = self.kwargs.get('pk') + bill = self.orchestra.retrieve_bill_document(pk) + + return HttpResponse(bill) + + class MailView(ServiceListView): service_class = MailService template_name = "musician/mail.html"