Refactor views related to billing

This commit is contained in:
Santiago L 2023-11-23 10:46:56 +01:00
parent e8e1d2240e
commit 2e659dbc26
1 changed files with 39 additions and 20 deletions

View File

@ -8,6 +8,7 @@ from django.core.exceptions import ImproperlyConfigured
from django.core.mail import mail_managers from django.core.mail import mail_managers
from django.http import (HttpResponse, HttpResponseNotFound, from django.http import (HttpResponse, HttpResponseNotFound,
HttpResponseRedirect) HttpResponseRedirect)
from django.shortcuts import get_object_or_404
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils import translation from django.utils import translation
from django.utils.html import format_html from django.utils.html import format_html
@ -21,7 +22,10 @@ from django.views.generic.list import ListView
from requests.exceptions import HTTPError from requests.exceptions import HTTPError
from orchestra import get_version from orchestra import get_version
from orchestra.contrib.bills.models import Bill
from orchestra.contrib.domains.models import Domain from orchestra.contrib.domains.models import Domain
from orchestra.contrib.saas.models import SaaS
from orchestra.utils.html import html_to_pdf
# from .auth import login as auth_login # from .auth import login as auth_login
from .auth import logout as auth_logout from .auth import logout as auth_logout
@ -29,8 +33,10 @@ from .forms import (LoginForm, MailboxChangePasswordForm, MailboxCreateForm,
MailboxUpdateForm, MailForm) MailboxUpdateForm, MailForm)
from .mixins import (CustomContextMixin, ExtendedPaginationMixin, from .mixins import (CustomContextMixin, ExtendedPaginationMixin,
UserTokenRequiredMixin) UserTokenRequiredMixin)
from .models import (Address, Bill, DatabaseService, Mailbox, from .models import Address
MailinglistService, PaymentSource, SaasService) from .models import Bill as BillService
from .models import (DatabaseService, Mailbox, MailinglistService,
PaymentSource, SaasService)
from .settings import ALLOWED_RESOURCES from .settings import ALLOWED_RESOURCES
from .utils import get_bootstraped_percent from .utils import get_bootstraped_percent
@ -148,35 +154,35 @@ def profile_set_language(request, code):
class ServiceListView(CustomContextMixin, ExtendedPaginationMixin, UserTokenRequiredMixin, ListView): class ServiceListView(CustomContextMixin, ExtendedPaginationMixin, UserTokenRequiredMixin, ListView):
"""Base list view to all services""" """Base list view to all services"""
service_class = None model = None
template_name = "musician/service_list.html" template_name = "musician/service_list.html"
def get_queryset(self): def get_queryset(self):
if self.service_class is None or self.service_class.api_name is None: if self.model is None :
raise ImproperlyConfigured( raise ImproperlyConfigured(
"ServiceListView requires a definiton of 'service'") "ServiceListView requires definiton of 'model' attribute")
queryfilter = self.get_queryfilter() queryfilter = self.get_queryfilter()
json_qs = self.orchestra.retrieve_service_list( qs = self.model.objects.filter(account=self.request.user, **queryfilter)
self.service_class.api_name,
querystring=queryfilter, return qs
)
return [self.service_class.new_from_json(data) for data in json_qs]
def get_queryfilter(self): def get_queryfilter(self):
"""Does nothing by default. Should be implemented on subclasses""" """Does nothing by default. Should be implemented on subclasses"""
return '' return {}
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context.update({ context.update({
'service': self.service_class, # TODO(@slamora): check where is used on the template
'service': self.model.__name__,
}) })
return context return context
class BillingView(ServiceListView): class BillingView(ServiceListView):
service_class = Bill service_class = BillService
model = Bill
template_name = "musician/billing.html" template_name = "musician/billing.html"
extra_context = { extra_context = {
# Translators: This message appears on the page title # Translators: This message appears on the page title
@ -185,23 +191,35 @@ class BillingView(ServiceListView):
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
qs = sorted(qs, key=lambda x: x.created_on, reverse=True) qs = qs.order_by("-created_on")
for q in qs:
q.created_on = datetime.datetime.strptime(q.created_on, "%Y-%m-%d")
return qs return qs
class BillDownloadView(CustomContextMixin, UserTokenRequiredMixin, View): class BillDownloadView(CustomContextMixin, UserTokenRequiredMixin, View):
extra_context = { extra_context = {
# Translators: This message appears on the page title # Translators: This message appears on the page title
'title': _('Download bill'), 'title': _('Download bill'),
} }
def get(self, request, *args, **kwargs): def get_object(self):
return get_object_or_404(
Bill.objects.filter(account=self.request.user),
pk=self.kwargs.get('pk') pk=self.kwargs.get('pk')
bill = self.orchestra.retrieve_bill_document(pk) )
return HttpResponse(bill) def get(self, request, *args, **kwargs):
# NOTE: this is a copy of method document() on orchestra.contrib.bills.api.BillViewSet
bill = self.get_object()
# TODO(@slamora): implement download as PDF, now only HTML is reachable via link
content_type = request.META.get('HTTP_ACCEPT')
if content_type == 'application/pdf':
pdf = html_to_pdf(bill.html or bill.render())
return HttpResponse(pdf, content_type='application/pdf')
else:
return HttpResponse(bill.html or bill.render())
class MailView(ServiceListView): class MailView(ServiceListView):
@ -509,6 +527,7 @@ class DatabasesView(ServiceListView):
class SaasView(ServiceListView): class SaasView(ServiceListView):
service_class = SaasService service_class = SaasService
model = SaaS
template_name = "musician/saas.html" template_name = "musician/saas.html"
extra_context = { extra_context = {
# Translators: This message appears on the page title # Translators: This message appears on the page title