Set one payment method as primary, allow updates
This commit is contained in:
		
					parent
					
						
							
								f2a797874a
							
						
					
				
			
			
				commit
				
					
						89c705f7d2
					
				
			
		
					 4 changed files with 45 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -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),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue