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