From 89c705f7d205874e9b2f04a28e465259ec9bf4b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Floure?= Date: Thu, 5 Mar 2020 15:19:25 +0100 Subject: [PATCH] Set one payment method as primary, allow updates --- .../migrations/0003_auto_20200305_1354.py | 18 +++++++++++++++ .../uncloud/uncloud_pay/models.py | 22 +++++++++---------- .../uncloud/uncloud_pay/serializers.py | 5 +++-- .../uncloud/uncloud_pay/views.py | 13 +++++++++++ 4 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 uncloud_django_based/uncloud/uncloud_pay/migrations/0003_auto_20200305_1354.py diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0003_auto_20200305_1354.py b/uncloud_django_based/uncloud/uncloud_pay/migrations/0003_auto_20200305_1354.py new file mode 100644 index 0000000..d99ece7 --- /dev/null +++ b/uncloud_django_based/uncloud/uncloud_pay/migrations/0003_auto_20200305_1354.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.3 on 2020-03-05 13:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('uncloud_pay', '0002_auto_20200305_1524.py'), + ] + + operations = [ + migrations.AlterField( + model_name='paymentmethod', + name='primary', + field=models.BooleanField(default=False, editable=False), + ), + ] diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py index 10ae985..f7aee62 100644 --- a/uncloud_django_based/uncloud/uncloud_pay/models.py +++ b/uncloud_django_based/uncloud/uncloud_pay/models.py @@ -4,9 +4,7 @@ from django.contrib.auth import get_user_model from django.core.validators import MinValueValidator from django.utils.translation import gettext_lazy as _ from django.utils import timezone -from django.dispatch import receiver from django.core.exceptions import ObjectDoesNotExist -import django.db.models.signals as signals import uuid from functools import reduce @@ -106,7 +104,7 @@ class PaymentMethod(models.Model): ), default='stripe') description = models.TextField() - primary = models.BooleanField(default=True) + primary = models.BooleanField(default=False, editable=False) # Only used for "Stripe" source stripe_payment_method_id = models.CharField(max_length=32, blank=True, null=True) @@ -149,22 +147,24 @@ class PaymentMethod(models.Model): else: raise Exception('This payment method is unsupported/cannot be charged.') + def set_as_primary_for(self, user): + methods = PaymentMethod.objects.filter(owner=user, primary=True) + for method in methods: + print(method) + method.primary = False + method.save() + + self.primary = True + self.save() def get_primary_for(user): methods = PaymentMethod.objects.filter(owner=user) for method in methods: - # Do we want to do something with non-primary method? - if method.active and method.primary: + if method.primary: return method return None - class Meta: - # TODO: limit to one primary method per user. - # unique_together is no good since it won't allow more than one - # non-primary method. - pass - ### # Bills. diff --git a/uncloud_django_based/uncloud/uncloud_pay/serializers.py b/uncloud_django_based/uncloud/uncloud_pay/serializers.py index f408d1b..72316a6 100644 --- a/uncloud_django_based/uncloud/uncloud_pay/serializers.py +++ b/uncloud_django_based/uncloud/uncloud_pay/serializers.py @@ -20,7 +20,7 @@ class PaymentMethodSerializer(serializers.ModelSerializer): class UpdatePaymentMethodSerializer(serializers.ModelSerializer): class Meta: model = PaymentMethod - fields = ['description', 'primary'] + fields = ['description'] class ChargePaymentMethodSerializer(serializers.Serializer): amount = serializers.DecimalField(max_digits=10, decimal_places=2) @@ -29,7 +29,8 @@ class CreatePaymentMethodSerializer(serializers.ModelSerializer): please_visit = serializers.CharField(read_only=True) class Meta: model = PaymentMethod - fields = ['source', 'description', 'primary', 'please_visit'] + fields = ['uuid', 'primary', 'source', 'description', 'please_visit'] + read_only_field = ['uuid', 'primary'] ### # Orders & Products. diff --git a/uncloud_django_based/uncloud/uncloud_pay/views.py b/uncloud_django_based/uncloud/uncloud_pay/views.py index 567874d..762a3c0 100644 --- a/uncloud_django_based/uncloud/uncloud_pay/views.py +++ b/uncloud_django_based/uncloud/uncloud_pay/views.py @@ -64,6 +64,10 @@ class PaymentMethodViewSet(viewsets.ModelViewSet): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) + # Set newly created method as primary if no other method is. + if PaymentMethod.get_primary_for(request.user) == None: + serializer.validated_data['primary'] = True + if serializer.validated_data['source'] == "stripe": # Retrieve Stripe customer ID for user. customer_id = uncloud_stripe.get_customer_id_for(request.user) @@ -109,6 +113,7 @@ class PaymentMethodViewSet(viewsets.ModelViewSet): @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() + if payment_method.source != 'stripe': return Response( {'error': 'This is not a Stripe-based payment method.'}, @@ -163,6 +168,14 @@ class PaymentMethodViewSet(viewsets.ModelViewSet): error = 'Could not fetch payment method from stripe. Please try again.' return Response({'error': error}) + @action(detail=True, methods=['post'], url_path='set-as-primary') + def set_as_primary(self, request, pk=None): + payment_method = self.get_object() + payment_method.set_as_primary_for(request.user) + + serializer = self.get_serializer(payment_method) + return Response(serializer.data) + ### # Bills and Orders.