from django.shortcuts import render from django.db import transaction from django.contrib.auth import get_user_model from rest_framework import viewsets, permissions, status, views from rest_framework.renderers import TemplateHTMLRenderer from rest_framework.response import Response from rest_framework.decorators import action from rest_framework.reverse import reverse from rest_framework.decorators import renderer_classes import json from .models import * from .serializers import * from datetime import datetime import uncloud_pay.stripe as uncloud_stripe ### # Standard user views: class BalanceViewSet(viewsets.ViewSet): # here we return a number # number = sum(payments) - sum(bills) #bills = Bill.objects.filter(owner=self.request.user) #payments = Payment.objects.filter(owner=self.request.user) # sum_paid = sum([ amount for amount payments..,. ]) # you get the picture # sum_to_be_paid = sum([ amount for amount bills..,. ]) # you get the picture pass class BillViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = BillSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return Bill.objects.filter(owner=self.request.user) def unpaid(self, request): return Bill.objects.filter(owner=self.request.user, paid=False) class PaymentViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = PaymentSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return Payment.objects.filter(owner=self.request.user) class OrderViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = OrderSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return Order.objects.filter(owner=self.request.user) class UserViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = UserSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return get_user_model().objects.all() class PaymentMethodViewSet(viewsets.ModelViewSet): permission_classes = [permissions.IsAuthenticated] def get_serializer_class(self): if self.action == 'create': return CreatePaymentMethodSerializer elif self.action == 'charge': return ChargePaymentMethodSerializer else: return PaymentMethodSerializer def get_queryset(self): return PaymentMethod.objects.filter(owner=self.request.user) # XXX: Handling of errors is far from great down there. @transaction.atomic def create(self, request): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) payment_method = PaymentMethod.objects.create(owner=request.user, **serializer.validated_data) if serializer.validated_data['source'] == "stripe": # Retrieve Stripe customer ID for user. customer_id = uncloud_stripe.get_customer_id_for(request.user) if customer_id == None: return Response( {'error': 'Could not resolve customer stripe ID.'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) # TODO: handle error setup_intent = uncloud_stripe.create_setup_intent(customer_id) payment_method = PaymentMethod.objects.create( owner=request.user, stripe_setup_intent_id=setup_intent['response_object']['id'], **serializer.validated_data) # TODO: find a way to use reverse properly: # https://www.django-rest-framework.org/api-guide/reverse/ query= "payment-method/{}/register-stripe-cc".format( payment_method.uuid ) stripe_registration_url = reverse('api-root', request=request) + query return Response({'please_visit': stripe_registration_url}) return Response(serializer.data) @action(detail=True, methods=['post']) def charge(self, request, pk=None): payment_method = self.get_object() serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) amount = serializer.validated_data['amount'] try: payment = payment_method.charge(amount) output_serializer = PaymentSerializer(payment) return Response(output_serializer.data) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) @action(detail=True, methods=['get'], url_path='register-stripe-cc', renderer_classes=[TemplateHTMLRenderer]) def register_stripe_cc(self, request, pk=None): payment_method = self.get_object() setup_intent = uncloud_stripe.get_setup_intent( payment_method.stripe_setup_intent_id) # Render stripe card registration form. template_args = { 'client_secret': setup_intent["response_object"]["client_secret"], 'stripe_pk': uncloud_stripe.public_api_key } return Response(template_args, template_name='stripe-payment.html.j2') @action(detail=True, methods=['post'], url_path='register-stripe-cc') def register_stripe_cc(self, request, pk=None): payment_method = self.get_object() setup_intent = uncloud_stripe.get_setup_intent( payment_method.stripe_setup_intent_id) # Card had been registered, fetching payment method. payment_method_id = setup_intent["response_object"].payment_method if payment_method_id: payment_method.stripe_payment_method_id = payment_method_id payment_method.save() return Response({ 'uuid': payment_method.uuid, 'activated': payment_method.active}) else: error = 'Could not fetch payment method from stripe. Please try again.' return Response({'error': error}) ### # Admin views. class AdminPaymentViewSet(viewsets.ModelViewSet): serializer_class = PaymentSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return Payment.objects.all() def create(self, request): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save(timestamp=datetime.now()) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) class AdminBillViewSet(viewsets.ModelViewSet): serializer_class = BillSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return Bill.objects.all() def unpaid(self, request): return Bill.objects.filter(owner=self.request.user, paid=False) def create(self, request): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save(creation_date=datetime.now()) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) class AdminOrderViewSet(viewsets.ModelViewSet): serializer_class = OrderSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return Order.objects.all()