Remove poetry #93019
159
looper/views/settings.py
Normal file
159
looper/views/settings.py
Normal file
@ -0,0 +1,159 @@
|
||||
import logging
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.views.generic import UpdateView, ListView, DeleteView, DetailView, View
|
||||
import stripe
|
||||
|
||||
from .. import forms, models, pdf, stripe_utils
|
||||
from looper import admin_log
|
||||
import looper.views.checkout
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@login_required
|
||||
def settings_receipts(request):
|
||||
order_set = request.user.customer.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.customer.order_set.paid()
|
||||
|
||||
|
||||
class ReceiptPDFView(ReceiptView):
|
||||
template_name = 'looper/settings/receipt_pdf.html'
|
||||
response_class = pdf.PDFResponse
|
||||
|
||||
|
||||
class BillingAddressView(LoginRequiredMixin, UpdateView):
|
||||
template_name = 'looper/settings/billing_address.html'
|
||||
form_class = forms.AddressForm
|
||||
model = models.Address
|
||||
success_url = reverse_lazy('looper:settings_billing_info')
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return self.request.user.customer.billing_address
|
||||
|
||||
|
||||
class PaymentMethodsView(LoginRequiredMixin, ListView):
|
||||
template_name = 'looper/settings/payment_methods.html'
|
||||
model = models.PaymentMethod
|
||||
|
||||
def get_queryset(self):
|
||||
superset = super().get_queryset()
|
||||
return superset.filter(customer=self.request.user.customer, is_deleted=False)
|
||||
|
||||
|
||||
class PaymentMethodDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
|
||||
template_name = 'looper/settings/payment_method_delete.html'
|
||||
model = models.PaymentMethod
|
||||
success_url = reverse_lazy('looper:payment_methods')
|
||||
|
||||
log = log.getChild('PaymentMethodDeleteView')
|
||||
|
||||
def has_permission(self) -> bool:
|
||||
payment_method = self.get_object()
|
||||
if self.request.user.customer.pk == payment_method.customer.pk:
|
||||
return True
|
||||
self.log.error(
|
||||
"User %d tried to delete someone else's payment method %d",
|
||||
self.request.user.pk,
|
||||
payment_method.pk,
|
||||
)
|
||||
return False
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
payment_method = self.get_object()
|
||||
message = (
|
||||
'User pk=%s is deleting payment method pk=%s',
|
||||
self.request.user.id,
|
||||
payment_method.pk,
|
||||
)
|
||||
admin_log.attach_log_entry(payment_method, message[0] % message[1:])
|
||||
|
||||
self.log.info(message)
|
||||
return super().delete(request, *args, **kwargs)
|
||||
|
||||
|
||||
class PaymentMethodChangeView(LoginRequiredMixin, View):
|
||||
"""Redirect to Stripe setup to switch a subscription's payment method."""
|
||||
|
||||
log = log.getChild('PaymentMethodChangeView')
|
||||
subscription: models.Subscription
|
||||
success_url = '/'
|
||||
cancel_url = 'settings_home'
|
||||
|
||||
def get_cancel_url(self):
|
||||
return reverse(self.cancel_url)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.subscription = get_object_or_404(
|
||||
request.user.customer.subscription_set, pk=kwargs['subscription_id']
|
||||
)
|
||||
success_url = self.request.build_absolute_uri(
|
||||
reverse(
|
||||
self.success_url,
|
||||
kwargs={
|
||||
'subscription_id': self.subscription.id,
|
||||
'stripe_session_id': 'CHECKOUT_SESSION_ID',
|
||||
}
|
||||
)
|
||||
)
|
||||
# we have to do it to avoid uri-encoding of curly braces,
|
||||
# otherwise stripe doesn't do the template substitution
|
||||
success_url = success_url.replace('CHECKOUT_SESSION_ID', '{CHECKOUT_SESSION_ID}', 1)
|
||||
cancel_url = self.request.build_absolute_uri(self.get_cancel_url())
|
||||
session = stripe_utils.setup_stripe_payment_method(
|
||||
self.subscription.currency.lower(),
|
||||
request.user.customer,
|
||||
success_url,
|
||||
cancel_url,
|
||||
setup_intent_metadata={
|
||||
'subscription_id': self.subscription.id,
|
||||
},
|
||||
)
|
||||
return redirect(session.url)
|
||||
|
||||
|
||||
class PaymentMethodChangeDoneView(LoginRequiredMixin, View):
|
||||
log = log.getChild('PaymentMethodChangeDoneView')
|
||||
subscription: models.Subscription
|
||||
success_url = '/'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.subscription = get_object_or_404(
|
||||
request.user.customer.subscription_set, pk=kwargs['subscription_id']
|
||||
)
|
||||
stripe_session_id = self.kwargs['stripe_session_id']
|
||||
stripe_session = stripe.checkout.Session.retrieve(
|
||||
stripe_session_id,
|
||||
expand=['setup_intent', 'setup_intent.payment_method']
|
||||
)
|
||||
setup_intent = stripe_session.setup_intent
|
||||
assert stripe_session.status == 'complete'
|
||||
assert setup_intent.status == 'succeeded'
|
||||
stripe_utils.process_setup_intent_for_subscription(setup_intent, self.subscription)
|
||||
|
||||
return redirect(self.success_url)
|
Loading…
Reference in New Issue
Block a user