Changeset View
Changeset View
Standalone View
Standalone View
looper/views/settings.py
| import logging | import logging | ||||
| from django.contrib.auth.decorators import login_required | |||||
| from django.contrib.auth.mixins import LoginRequiredMixin | from django.contrib.auth.mixins import LoginRequiredMixin | ||||
| from django.http import HttpResponse, HttpResponseForbidden, HttpResponseRedirect | from django.http import HttpResponse, HttpResponseForbidden, HttpResponseRedirect | ||||
| from django.shortcuts import get_object_or_404, render | from django.shortcuts import get_object_or_404, render | ||||
| from django.urls import reverse_lazy | from django.urls import reverse_lazy | ||||
| from django.views.generic import UpdateView, ListView, FormView, DeleteView | from django.views.generic import UpdateView, ListView, DeleteView, DetailView | ||||
| import looper.views.checkout | import looper.views.checkout | ||||
| from .. import exceptions, forms, models | from .. import exceptions, forms, models | ||||
| from .. import pdf | |||||
sybren: Either do `from .. import exceptions, forms, models, pdf` or split everything up into separate… | |||||
| log = logging.getLogger(__name__) | log = logging.getLogger(__name__) | ||||
| @login_required | |||||
| def settings_receipts(request): | |||||
| order_set = request.user.order_set | |||||
| orders = order_set.paid().select_related('subscription__plan') | |||||
| context = { | |||||
| 'orders': orders, | |||||
| 'can_woosh': request.user.is_staff and request.user.has_perm('looper.change_order') | |||||
| } | |||||
| return render(request, 'looper/settings/receipts.html', context=context) | |||||
| class ReceiptView(LoginRequiredMixin, DetailView): | |||||
| template_name = 'looper/settings/receipt.html' | |||||
| pk_url_kwarg = 'order_id' | |||||
| def get_queryset(self): | |||||
| """Limit the allowed order IDs to the ones owned by the user. | |||||
| Staff users with the permission to view orders can access | |||||
| all orders of all users. | |||||
| """ | |||||
| user = self.request.user | |||||
| if user.is_staff and user.has_perm('looper.view_order'): | |||||
| return looper.models.Order.objects.paid() | |||||
| return user.order_set.paid() | |||||
| class ReceiptPDFView(ReceiptView): | |||||
| template_name = 'looper/settings/receipt_pdf.html' | |||||
| response_class = pdf.PDFResponse | |||||
| class PersonalInfoView(LoginRequiredMixin, UpdateView): | class PersonalInfoView(LoginRequiredMixin, UpdateView): | ||||
| template_name = 'settings/personal_info.html' | template_name = 'looper/settings/personal_info.html' | ||||
| form_class = forms.CustomerForm | form_class = forms.CustomerForm | ||||
| model = models.Customer | model = models.Customer | ||||
| success_url = reverse_lazy('looper:settings_personal_info') | success_url = reverse_lazy('looper:settings_personal_info') | ||||
| def get_object(self, queryset=None): | def get_object(self, queryset=None): | ||||
| return self.request.user.customer | return self.request.user.customer | ||||
| class BillingAddressView(LoginRequiredMixin, UpdateView): | class BillingAddressView(LoginRequiredMixin, UpdateView): | ||||
| template_name = 'settings/billing_address.html' | template_name = 'looper/settings/billing_address.html' | ||||
| form_class = forms.AddressForm | form_class = forms.AddressForm | ||||
| model = models.Address | model = models.Address | ||||
| success_url = reverse_lazy('looper:settings_billing_info') | success_url = reverse_lazy('looper:settings_billing_info') | ||||
| def get_object(self, queryset=None): | def get_object(self, queryset=None): | ||||
| return self.request.user.customer.billing_address | return self.request.user.customer.billing_address | ||||
| class PaymentMethodsView(LoginRequiredMixin, ListView): | class PaymentMethodsView(LoginRequiredMixin, ListView): | ||||
| template_name = 'settings/payment_methods.html' | template_name = 'looper/settings/payment_methods.html' | ||||
| model = models.PaymentMethod | model = models.PaymentMethod | ||||
| def get_queryset(self): | def get_queryset(self): | ||||
| superset = super().get_queryset() | superset = super().get_queryset() | ||||
| return superset.filter(user=self.request.user, is_deleted=False) | return superset.filter(user=self.request.user, is_deleted=False) | ||||
| class PaymentMethodDeleteView(LoginRequiredMixin, DeleteView): | class PaymentMethodDeleteView(LoginRequiredMixin, DeleteView): | ||||
| template_name = 'settings/payment_method_delete.html' | template_name = 'looper/settings/payment_method_delete.html' | ||||
| model = models.PaymentMethod | model = models.PaymentMethod | ||||
| success_url = reverse_lazy('looper:payment_methods') | success_url = reverse_lazy('looper:payment_methods') | ||||
| log = log.getChild('PaymentMethodDeleteView') | log = log.getChild('PaymentMethodDeleteView') | ||||
| def delete(self, request, *args, **kwargs): | def delete(self, request, *args, **kwargs): | ||||
| payment_method = self.get_object() | payment_method = self.get_object() | ||||
| if self.request.user.id != payment_method.user.id: | if self.request.user.id != payment_method.user.id: | ||||
| self.log.warning( | self.log.warning( | ||||
| "User %d tried to delete someone else's payment method %d", | "User %d tried to delete someone else's payment method %d", | ||||
| self.request.user.pk, | self.request.user.pk, | ||||
| payment_method.pk, | payment_method.pk, | ||||
| ) | ) | ||||
| return HttpResponseForbidden(content='No access to this payment method') | return HttpResponseForbidden(content='No access to this payment method') | ||||
| self.log.info('Deleting payment method pk=%d', payment_method.pk) | self.log.info('Deleting payment method pk=%d', payment_method.pk) | ||||
| return super().delete(request, *args, **kwargs) | return super().delete(request, *args, **kwargs) | ||||
| class PaymentMethodChangeView(looper.views.checkout.AbstractPaymentView): | class PaymentMethodChangeView(looper.views.checkout.AbstractPaymentView): | ||||
| """Use the Braintree drop-in UI to switch a subscription's payment method.""" | """Use the Braintree drop-in UI to switch a subscription's payment method.""" | ||||
| template_name = 'settings/payment_method_change.html' | template_name = 'looper/settings/payment_method_change.html' | ||||
| form_class = forms.ChangePaymentMethodForm | form_class = forms.ChangePaymentMethodForm | ||||
| success_url = '/settings/' | success_url = '/settings/' | ||||
| log = log.getChild('PaymentMethodChangeView') | log = log.getChild('PaymentMethodChangeView') | ||||
| subscription: models.Subscription | subscription: models.Subscription | ||||
| def dispatch(self, request, *args, **kwargs): | def dispatch(self, request, *args, **kwargs): | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | def form_valid(self, form: forms.ChangePaymentMethodForm) -> HttpResponse: | ||||
| self.erase_client_token() | self.erase_client_token() | ||||
| return HttpResponseRedirect(form.cleaned_data['next_url_after_done'] or self.success_url) | return HttpResponseRedirect(form.cleaned_data['next_url_after_done'] or self.success_url) | ||||
| class PaymentMethodReplaceView(looper.views.checkout.AbstractPaymentView): | class PaymentMethodReplaceView(looper.views.checkout.AbstractPaymentView): | ||||
| """Use the Braintree drop-in UI to replace a payment method.""" | """Use the Braintree drop-in UI to replace a payment method.""" | ||||
| template_name = 'settings/payment_method_replace.html' | template_name = 'looper/settings/payment_method_replace.html' | ||||
| form_class = forms.PaymentMethodReplaceForm | form_class = forms.PaymentMethodReplaceForm | ||||
| success_url = reverse_lazy('looper:payment_methods') | success_url = reverse_lazy('looper:payment_methods') | ||||
| log = log.getChild('PaymentMethodReplaceView') | log = log.getChild('PaymentMethodReplaceView') | ||||
| paymeth: models.PaymentMethod | paymeth: models.PaymentMethod | ||||
| currency: str | currency: str | ||||
| def dispatch(self, request, *args, **kwargs): | def dispatch(self, request, *args, **kwargs): | ||||
| # This is normally done in super().dispatch(), but we use | # This is normally done in super().dispatch(), but we use | ||||
| # request.user.paymentmethod_set which doesn't exist on AnonymousUser. | # request.user.paymentmethod_set which doesn't exist on AnonymousUser. | ||||
| if not request.user.is_authenticated: | if not request.user.is_authenticated: | ||||
| return self.handle_no_permission() | return self.handle_no_permission() | ||||
| self.paymeth = get_object_or_404(request.user.paymentmethod_set, pk=kwargs['pk']) | self.paymeth = get_object_or_404(request.user.paymentmethod_set, pk=kwargs['pk']) | ||||
| self.currency = self.determine_currency() | self.currency = self.determine_currency() | ||||
| if not self.currency: | if not self.currency: | ||||
| return render( | return render( | ||||
| request, | request, | ||||
| 'settings/payment_method_not_used.html', | 'looper/settings/payment_method_not_used.html', | ||||
| { | { | ||||
| 'paymeth': self.paymeth, | 'paymeth': self.paymeth, | ||||
| }, | }, | ||||
| ) | ) | ||||
| return super().dispatch(request, *args, **kwargs) | return super().dispatch(request, *args, **kwargs) | ||||
| def determine_currency(self) -> str: | def determine_currency(self) -> str: | ||||
| ▲ Show 20 Lines • Show All 58 Lines • Show Last 20 Lines | |||||
Either do from .. import exceptions, forms, models, pdf or split everything up into separate lines.