Set one payment method as primary, allow updates

This commit is contained in:
fnux 2020-03-05 15:19:25 +01:00
parent f2a797874a
commit 89c705f7d2
4 changed files with 45 additions and 13 deletions

View file

@ -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),
),
]

View file

@ -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.

View file

@ -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.

View file

@ -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.