Add view to retrieve bill document.

This commit is contained in:
Santiago Lamora 2019-12-17 15:15:58 +01:00
parent 186d20ec20
commit c2d865d664
5 changed files with 29 additions and 11 deletions

View file

@ -28,6 +28,7 @@ API_PATHS = {
# other # other
'bill-list': 'bills/', 'bill-list': 'bills/',
'bill-document': 'bills/{pk}/document/',
'payment-source-list': 'payment-sources/', 'payment-source-list': 'payment-sources/',
} }
@ -59,7 +60,7 @@ class Orchestra(object):
return response.json().get("token", None) 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"] assert verb in ["HEAD", "GET", "POST", "PATCH", "PUT", "DELETE"]
if resource is not None: if resource is not None:
url = self.build_absolute_uri(resource) url = self.build_absolute_uri(resource)
@ -77,7 +78,10 @@ class Orchestra(object):
response.raise_for_status() response.raise_for_status()
status = response.status_code status = response.status_code
output = response.json() if render_as == "json":
output = response.json()
else:
output = response.content
return status, output return status, output
@ -94,6 +98,15 @@ class Orchestra(object):
raise PermissionError("Cannot retrieve profile of an anonymous user.") raise PermissionError("Cannot retrieve profile of an anonymous user.")
return UserAccount.new_from_json(output[0]) 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): def retrieve_domain(self, pk):
path = API_PATHS.get('domain-detail').format_map({'pk': pk}) path = API_PATHS.get('domain-detail').format_map({'pk': pk})

View file

@ -51,6 +51,7 @@ class OrchestraModel:
class Bill(OrchestraModel): class Bill(OrchestraModel):
api_name = 'bill' api_name = 'bill'
param_defaults = { param_defaults = {
"id": None,
"number": "1", "number": "1",
"type": "INVOICE", "type": "INVOICE",
"total": 0.0, "total": 0.0,
@ -60,12 +61,6 @@ class Bill(OrchestraModel):
"comments": "", "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): class BillingContact(OrchestraModel):
param_defaults = { param_defaults = {

View file

@ -30,7 +30,7 @@
<td>{{ bill.created_on }}</td> <td>{{ bill.created_on }}</td>
<td>{{ bill.type }}</td> <td>{{ bill.type }}</td>
<td>{{ bill.total|floatformat:2|localize }}€</td> <td>{{ bill.total|floatformat:2|localize }}€</td>
<td><a class="text-dark" href="{{ bill.pdf_url }}" target="_blank" rel="noopener noreferrer"><i class="fas fa-file-pdf"></i></a></td> <td><a class="text-dark" href="{% url 'musician:bill-download' bill.id %}" target="_blank" rel="noopener noreferrer"><i class="fas fa-file-pdf"></i></a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View file

@ -16,7 +16,8 @@ urlpatterns = [
path('auth/logout/', views.LogoutView.as_view(), name='logout'), path('auth/logout/', views.LogoutView.as_view(), name='logout'),
path('dashboard/', views.DashboardView.as_view(), name='dashboard'), path('dashboard/', views.DashboardView.as_view(), name='dashboard'),
path('domains/<int:pk>/', views.DomainDetailView.as_view(), name='domain-detail'), path('domains/<int:pk>/', 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/<int:pk>/download/', views.BillDownloadView.as_view(), name='bill-download'),
path('profile/', views.ProfileView.as_view(), name='profile'), path('profile/', views.ProfileView.as_view(), name='profile'),
path('mails/', views.MailView.as_view(), name='mails'), path('mails/', views.MailView.as_view(), name='mails'),
path('mailing-lists/', views.MailingListsView.as_view(), name='mailing-lists'), path('mailing-lists/', views.MailingListsView.as_view(), name='mailing-lists'),

View file

@ -1,11 +1,12 @@
from itertools import groupby from itertools import groupby
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.http import is_safe_url from django.utils.http import is_safe_url
from django.utils.translation import gettext_lazy as _ 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.base import RedirectView, TemplateView
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
@ -133,6 +134,14 @@ class BillingView(ServiceListView):
template_name = "musician/billing.html" 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): class MailView(ServiceListView):
service_class = MailService service_class = MailService
template_name = "musician/mail.html" template_name = "musician/mail.html"