diff --git a/djstripe/contrib/rest_framework/views.py b/djstripe/contrib/rest_framework/views.py index 9135886db8..65df08b0f0 100644 --- a/djstripe/contrib/rest_framework/views.py +++ b/djstripe/contrib/rest_framework/views.py @@ -26,7 +26,7 @@ class SubscriptionRestView(APIView): permission_classes = (IsAuthenticated,) - def get(self, request, format=None): + def get(self, request, **kwargs): """ Returns the customer's valid subscriptions. Returns with status code 200. @@ -40,7 +40,7 @@ def get(self, request, format=None): except: return Response(status=status.HTTP_204_NO_CONTENT) - def post(self, request, format=None): + def post(self, request, **kwargs): """ Create a new current subscription for the user. Returns with status code 201. @@ -50,7 +50,7 @@ def post(self, request, format=None): if serializer.is_valid(): try: - customer, created = Customer.get_or_create( + customer, _created = Customer.get_or_create( subscriber=subscriber_request_callback(self.request) ) customer.add_card(serializer.data["stripe_token"]) @@ -68,7 +68,7 @@ def post(self, request, format=None): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - def delete(self, request, format=None): + def delete(self, request, **kwargs): """ Marks the users current subscription as cancelled. Returns with status code 204. diff --git a/djstripe/event_handlers.py b/djstripe/event_handlers.py index 4e1639541a..cfe5d654a1 100644 --- a/djstripe/event_handlers.py +++ b/djstripe/event_handlers.py @@ -46,7 +46,12 @@ def customer_webhook_handler(event, event_data, event_type, event_subtype): if crud_type.valid and event.customer: # As customers are tied to local users, djstripe will not create # customers that do not already exist locally. - _handle_crud_type_event(target_cls=Customer, event_data=event_data, event_subtype=event_subtype, crud_type=crud_type) + _handle_crud_type_event( + target_cls=Customer, + event_data=event_data, + event_subtype=event_subtype, + crud_type=crud_type + ) @webhooks.handler("customer.source") @@ -58,14 +63,24 @@ def customer_source_webhook_handler( # TODO: other sources if source_type == "card": - _handle_crud_type_event(target_cls=Card, event_data=event_data, event_subtype=event_subtype, customer=event.customer) + _handle_crud_type_event( + target_cls=Card, + event_data=event_data, + event_subtype=event_subtype, + customer=event.customer + ) @webhooks.handler("customer.subscription") def customer_subscription_webhook_handler(event, event_data, event_type, event_subtype): """ Handles updates for customer subscription objects. """ - _handle_crud_type_event(target_cls=Subscription, event_data=event_data, event_subtype=event_subtype, customer=event.customer) + _handle_crud_type_event( + target_cls=Subscription, + event_data=event_data, + event_subtype=event_subtype, + customer=event.customer + ) @webhooks.handler(["transfer", "charge", "invoice", "invoiceitem", "plan"]) @@ -80,7 +95,12 @@ def other_object_webhook_handler(event, event_data, event_type, event_subtype): "transfer": Transfer }.get(event_type) - _handle_crud_type_event(target_cls=target_cls, event_data=event_data, event_subtype=event_subtype, customer=event.customer) + _handle_crud_type_event( + target_cls=target_cls, + event_data=event_data, + event_subtype=event_subtype, + customer=event.customer + ) # diff --git a/djstripe/fields.py b/djstripe/fields.py index 861c7ef93e..fca6878c09 100644 --- a/djstripe/fields.py +++ b/djstripe/fields.py @@ -113,7 +113,8 @@ class StripeBooleanField(StripeFieldMixin, models.BooleanField): def __init__(self, *args, **kwargs): if kwargs.get("deprecated", False): - raise ImproperlyConfigured("Boolean field cannot be deprecated. Change field type to StripeNullBooleanField") + raise ImproperlyConfigured("Boolean field cannot be deprecated. Change field type to " + "StripeNullBooleanField") super(StripeBooleanField, self).__init__(*args, **kwargs) diff --git a/djstripe/migrations/0001_initial.py b/djstripe/migrations/0001_initial.py index d3938014cf..e83a74e3a6 100644 --- a/djstripe/migrations/0001_initial.py +++ b/djstripe/migrations/0001_initial.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +from django.conf import settings from django.db import models, migrations -import jsonfield.fields import django.utils.timezone -from django.conf import settings +import jsonfield.fields import model_utils.fields @@ -19,8 +19,10 @@ class Migration(migrations.Migration): name='Charge', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('card_last_4', models.CharField(max_length=4, blank=True)), ('card_kind', models.CharField(max_length=50, blank=True)), @@ -43,8 +45,10 @@ class Migration(migrations.Migration): name='CurrentSubscription', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('plan', models.CharField(max_length=100)), ('quantity', models.IntegerField()), ('start', models.DateTimeField()), @@ -67,8 +71,10 @@ class Migration(migrations.Migration): name='Customer', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('card_fingerprint', models.CharField(max_length=200, blank=True)), ('card_last_4', models.CharField(max_length=4, blank=True)), @@ -85,8 +91,10 @@ class Migration(migrations.Migration): name='Event', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('kind', models.CharField(max_length=250)), ('livemode', models.BooleanField(default=False)), @@ -105,8 +113,10 @@ class Migration(migrations.Migration): name='EventProcessingException', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('data', models.TextField()), ('message', models.CharField(max_length=500)), ('traceback', models.TextField()), @@ -121,8 +131,10 @@ class Migration(migrations.Migration): name='Invoice', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(max_length=50)), ('attempted', models.NullBooleanField()), ('attempts', models.PositiveIntegerField(null=True)), @@ -145,8 +157,10 @@ class Migration(migrations.Migration): name='InvoiceItem', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(max_length=50)), ('amount', models.DecimalField(max_digits=7, decimal_places=2)), ('currency', models.CharField(max_length=10)), @@ -168,13 +182,18 @@ class Migration(migrations.Migration): name='Plan', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('name', models.CharField(max_length=100)), - ('currency', models.CharField(max_length=10, choices=[('usd', 'U.S. Dollars'), ('gbp', 'Pounds (GBP)'), ('eur', 'Euros')])), - ('interval', models.CharField(max_length=10, verbose_name='Interval type', choices=[('week', 'Week'), ('month', 'Month'), ('year', 'Year')])), - ('interval_count', models.IntegerField(default=1, null=True, verbose_name='Intervals between charges')), + ('currency', models.CharField(max_length=10, choices=[('usd', 'U.S. Dollars'), + ('gbp', 'Pounds (GBP)'), ('eur', 'Euros')])), + ('interval', models.CharField(max_length=10, verbose_name='Interval type', + choices=[('week', 'Week'), ('month', 'Month'), ('year', 'Year')])), + ('interval_count', models.IntegerField(default=1, null=True, + verbose_name='Intervals between charges')), ('amount', models.DecimalField(verbose_name='Amount (per period)', max_digits=7, decimal_places=2)), ('trial_period_days', models.IntegerField(null=True)), ], @@ -187,8 +206,10 @@ class Migration(migrations.Migration): name='Transfer', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('amount', models.DecimalField(max_digits=7, decimal_places=2)), ('status', models.CharField(max_length=25)), @@ -219,8 +240,10 @@ class Migration(migrations.Migration): name='TransferChargeFee', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('amount', models.DecimalField(max_digits=7, decimal_places=2)), ('application', models.TextField(null=True, blank=True)), ('description', models.TextField(null=True, blank=True)), diff --git a/djstripe/migrations/0001_squashed_0007_for_custom_subscriber_model.py b/djstripe/migrations/0001_squashed_0007_for_custom_subscriber_model.py index e92ab641f1..55cdd76e20 100644 --- a/djstripe/migrations/0001_squashed_0007_for_custom_subscriber_model.py +++ b/djstripe/migrations/0001_squashed_0007_for_custom_subscriber_model.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +from django.conf import settings from django.db import models, migrations -import jsonfield.fields import django.utils.timezone -from django.conf import settings +import jsonfield.fields import model_utils.fields + # Can't use the callable because the app registry is not ready yet. # Really trusting users here... bad idea? probably. DJSTRIPE_UNSAFE_SUBSCRIBER_MODEL = getattr(settings, "DJSTRIPE_SUBSCRIBER_MODEL", settings.AUTH_USER_MODEL) @@ -31,7 +32,10 @@ class Migration(migrations.Migration): # not that squashmigrations generates [(b'djstripe', '0001_initial'),.... # but for django in python3.X it needs to be [('djstripe', '0001_initial'),.... in order for the dependency # graph loader to remove the migrations this replaces - replaces = [('djstripe', '0001_initial'), ('djstripe', '0002_auto_20150122_2000'), ('djstripe', '0003_auto_20150128_0800'), ('djstripe', '0004_auto_20150427_1609'), ('djstripe', '0005_charge_captured'), ('djstripe', '0006_auto_20150602_1934'), ('djstripe', '0007_auto_20150625_1243')] + replaces = [('djstripe', '0001_initial'), ('djstripe', '0002_auto_20150122_2000'), + ('djstripe', '0003_auto_20150128_0800'), ('djstripe', '0004_auto_20150427_1609'), + ('djstripe', '0005_charge_captured'), ('djstripe', '0006_auto_20150602_1934'), + ('djstripe', '0007_auto_20150625_1243')] dependencies = [ DJSTRIPE_UNSAFE_SUBSCRIBER_MODEL_DEPENDENCY, @@ -42,8 +46,10 @@ class Migration(migrations.Migration): name='Charge', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('card_last_4', models.CharField(max_length=4, blank=True)), ('card_kind', models.CharField(max_length=50, blank=True)), @@ -65,8 +71,10 @@ class Migration(migrations.Migration): name='CurrentSubscription', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('plan', models.CharField(max_length=100)), ('quantity', models.IntegerField()), ('start', models.DateTimeField()), @@ -88,8 +96,10 @@ class Migration(migrations.Migration): name='Customer', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('card_fingerprint', models.CharField(max_length=200, blank=True)), ('card_last_4', models.CharField(max_length=4, blank=True)), @@ -105,8 +115,10 @@ class Migration(migrations.Migration): name='Event', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('kind', models.CharField(max_length=250)), ('livemode', models.BooleanField(default=False)), @@ -124,8 +136,10 @@ class Migration(migrations.Migration): name='EventProcessingException', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('data', models.TextField()), ('message', models.CharField(max_length=500)), ('traceback', models.TextField()), @@ -139,8 +153,10 @@ class Migration(migrations.Migration): name='Invoice', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(max_length=50)), ('attempted', models.NullBooleanField()), ('attempts', models.PositiveIntegerField(null=True)), @@ -162,8 +178,10 @@ class Migration(migrations.Migration): name='InvoiceItem', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(max_length=50)), ('amount', models.DecimalField(max_digits=7, decimal_places=2)), ('currency', models.CharField(max_length=10)), @@ -184,13 +202,18 @@ class Migration(migrations.Migration): name='Plan', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('name', models.CharField(max_length=100)), - ('currency', models.CharField(max_length=10, choices=[('usd', 'U.S. Dollars'), ('gbp', 'Pounds (GBP)'), ('eur', 'Euros')])), - ('interval', models.CharField(max_length=10, verbose_name='Interval type', choices=[('week', 'Week'), ('month', 'Month'), ('year', 'Year')])), - ('interval_count', models.IntegerField(default=1, null=True, verbose_name='Intervals between charges')), + ('currency', models.CharField(max_length=10, choices=[('usd', 'U.S. Dollars'), + ('gbp', 'Pounds (GBP)'), ('eur', 'Euros')])), + ('interval', models.CharField(max_length=10, verbose_name='Interval type', + choices=[('week', 'Week'), ('month', 'Month'), ('year', 'Year')])), + ('interval_count', models.IntegerField(default=1, null=True, + verbose_name='Intervals between charges')), ('amount', models.DecimalField(verbose_name='Amount (per period)', max_digits=7, decimal_places=2)), ('trial_period_days', models.IntegerField(null=True)), ], @@ -202,8 +225,10 @@ class Migration(migrations.Migration): name='Transfer', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('stripe_id', models.CharField(unique=True, max_length=50)), ('amount', models.DecimalField(max_digits=7, decimal_places=2)), ('status', models.CharField(max_length=25)), @@ -233,8 +258,10 @@ class Migration(migrations.Migration): name='TransferChargeFee', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), + ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, + verbose_name='created', editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, + verbose_name='modified', editable=False)), ('amount', models.DecimalField(max_digits=7, decimal_places=2)), ('application', models.TextField(null=True, blank=True)), ('description', models.TextField(null=True, blank=True)), diff --git a/djstripe/migrations/0009_auto_20160501_1838.py b/djstripe/migrations/0009_auto_20160501_1838.py index 709562ae2a..67648f10d2 100644 --- a/djstripe/migrations/0009_auto_20160501_1838.py +++ b/djstripe/migrations/0009_auto_20160501_1838.py @@ -1,13 +1,15 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import migrations, models -import djstripe.fields -import django.core.validators import datetime + +import django.core.validators +from django.db import migrations, models import django.utils.timezone import model_utils.fields +import djstripe.fields + class Migration(migrations.Migration): @@ -21,13 +23,23 @@ class Migration(migrations.Migration): name='Account', fields=[ ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(verbose_name='created', default=django.utils.timezone.now, editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(verbose_name='modified', default=django.utils.timezone.now, editable=False)), + ('created', model_utils.fields.AutoCreatedField(verbose_name='created', + default=django.utils.timezone.now, editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(verbose_name='modified', + default=django.utils.timezone.now, + editable=False)), ('stripe_id', djstripe.fields.StripeIdField(max_length=50, unique=True)), - ('livemode', djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False)), - ('stripe_timestamp', djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True)), - ('metadata', djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True)), - ('description', djstripe.fields.StripeTextField(blank=True, help_text='A description of this object.', null=True)), + ('livemode', djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False)), + ('stripe_timestamp', djstripe.fields.StripeDateTimeField( + help_text='The datetime this object was created in stripe.', null=True)), + ('metadata', djstripe.fields.StripeJSONField( + blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful\ + for storing additional information about an object in a structured format.', null=True)), + ('description', djstripe.fields.StripeTextField(blank=True, help_text='A description of this object.', + null=True)), ], options={ 'abstract': False, @@ -37,13 +49,23 @@ class Migration(migrations.Migration): name='StripeSource', fields=[ ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), - ('created', model_utils.fields.AutoCreatedField(verbose_name='created', default=django.utils.timezone.now, editable=False)), - ('modified', model_utils.fields.AutoLastModifiedField(verbose_name='modified', default=django.utils.timezone.now, editable=False)), + ('created', model_utils.fields.AutoCreatedField(verbose_name='created', + default=django.utils.timezone.now, editable=False)), + ('modified', model_utils.fields.AutoLastModifiedField(verbose_name='modified', + default=django.utils.timezone.now, + editable=False)), ('stripe_id', djstripe.fields.StripeIdField(max_length=50, unique=True)), - ('livemode', djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False)), - ('stripe_timestamp', djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True)), - ('metadata', djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True)), - ('description', djstripe.fields.StripeTextField(blank=True, help_text='A description of this object.', null=True)), + ('livemode', djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False)), + ('stripe_timestamp', djstripe.fields.StripeDateTimeField( + help_text='The datetime this object was created in stripe.', null=True)), + ('metadata', djstripe.fields.StripeJSONField( + blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful\ + for storing additional information about an object in a structured format.', null=True)), + ('description', djstripe.fields.StripeTextField(blank=True, help_text='A description of this object.', + null=True)), ], options={ 'abstract': False, @@ -52,26 +74,49 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Card', fields=[ - ('stripesource_ptr', models.OneToOneField(serialize=False, parent_link=True, primary_key=True, to='djstripe.StripeSource', auto_created=True)), + ('stripesource_ptr', models.OneToOneField(serialize=False, parent_link=True, primary_key=True, + to='djstripe.StripeSource', auto_created=True)), ('address_city', djstripe.fields.StripeTextField(help_text='Billing address city.', null=True)), ('address_country', djstripe.fields.StripeTextField(help_text='Billing address country.', null=True)), ('address_line1', djstripe.fields.StripeTextField(help_text='Billing address (Line 1).', null=True)), - ('address_line1_check', djstripe.fields.StripeCharField(choices=[('pass', 'Pass'), ('fail', 'Fail'), ('unavailable', 'Unavailable'), ('unknown', 'Unknown')], max_length=11, help_text='If ``address_line1`` was provided, results of the check.', null=True)), + ('address_line1_check', djstripe.fields.StripeCharField( + choices=[('pass', 'Pass'), ('fail', 'Fail'), ('unavailable', 'Unavailable'), + ('unknown', 'Unknown')], + max_length=11, help_text='If ``address_line1`` was provided, results of the check.', null=True)), ('address_line2', djstripe.fields.StripeTextField(help_text='Billing address (Line 2).', null=True)), ('address_state', djstripe.fields.StripeTextField(help_text='Billing address state.', null=True)), ('address_zip', djstripe.fields.StripeTextField(help_text='Billing address zip code.', null=True)), - ('address_zip_check', djstripe.fields.StripeCharField(choices=[('pass', 'Pass'), ('fail', 'Fail'), ('unavailable', 'Unavailable'), ('unknown', 'Unknown')], max_length=11, help_text='If ``address_zip`` was provided, results of the check.', null=True)), - ('brand', djstripe.fields.StripeCharField(choices=[('Visa', 'Visa'), ('American Express', 'American Express'), ('MasterCard', 'MasterCard'), ('Discover', 'Discover'), ('JCB', 'JCB'), ('Diners Club', 'Diners Club'), ('Unknown', 'Unknown')], max_length=16, help_text='Card brand.')), - ('country', djstripe.fields.StripeCharField(max_length=2, help_text='Two-letter ISO code representing the country of the card.')), - ('cvc_check', djstripe.fields.StripeCharField(choices=[('pass', 'Pass'), ('fail', 'Fail'), ('unavailable', 'Unavailable'), ('unknown', 'Unknown')], max_length=11, help_text='If a CVC was provided, results of the check.', null=True)), - ('dynamic_last4', djstripe.fields.StripeCharField(max_length=4, help_text='(For tokenized numbers only.) The last four digits of the device account number.', null=True)), + ('address_zip_check', djstripe.fields.StripeCharField( + choices=[('pass', 'Pass'), ('fail', 'Fail'), ('unavailable', 'Unavailable'), + ('unknown', 'Unknown')], + max_length=11, help_text='If ``address_zip`` was provided, results of the check.', null=True)), + ('brand', djstripe.fields.StripeCharField( + choices=[('Visa', 'Visa'), ('American Express', 'American Express'), ('MasterCard', 'MasterCard'), + ('Discover', 'Discover'), ('JCB', 'JCB'), ('Diners Club', 'Diners Club'), + ('Unknown', 'Unknown')], + max_length=16, help_text='Card brand.')), + ('country', djstripe.fields.StripeCharField( + max_length=2, help_text='Two-letter ISO code representing the country of the card.')), + ('cvc_check', djstripe.fields.StripeCharField( + choices=[('pass', 'Pass'), ('fail', 'Fail'), ('unavailable', 'Unavailable'), + ('unknown', 'Unknown')], + max_length=11, help_text='If a CVC was provided, results of the check.', null=True)), + ('dynamic_last4', djstripe.fields.StripeCharField( + max_length=4, + help_text='(For tokenized numbers only.) The last four digits of the device account number.', + null=True)), ('exp_month', djstripe.fields.StripeIntegerField(help_text='Card expiration month.')), ('exp_year', djstripe.fields.StripeIntegerField(help_text='Card expiration year.')), - ('fingerprint', djstripe.fields.StripeTextField(help_text='Uniquely identifies this particular card number.', null=True)), - ('funding', djstripe.fields.StripeCharField(choices=[('credit', 'Credit'), ('debit', 'Debit'), ('prepaid', 'Prepaid'), ('unknown', 'Unknown')], max_length=7, help_text='Card funding type.')), + ('fingerprint', djstripe.fields.StripeTextField( + help_text='Uniquely identifies this particular card number.', null=True)), + ('funding', djstripe.fields.StripeCharField( + choices=[('credit', 'Credit'), ('debit', 'Debit'), ('prepaid', 'Prepaid'), ('unknown', 'Unknown')], + max_length=7, help_text='Card funding type.')), ('last4', djstripe.fields.StripeCharField(max_length=4, help_text='Last four digits of Card number.')), ('name', djstripe.fields.StripeTextField(help_text='Cardholder name.', null=True)), - ('tokenization_method', djstripe.fields.StripeCharField(choices=[('apple_pay', 'Apple Pay'), ('android_pay', 'Android Pay')], max_length=11, help_text='If the card number is tokenized, this is the method that was used.', null=True)), + ('tokenization_method', djstripe.fields.StripeCharField( + choices=[('apple_pay', 'Apple Pay'), ('android_pay', 'Android Pay')], max_length=11, + help_text='If the card number is tokenized, this is the method that was used.', null=True)), ], options={ 'abstract': False, @@ -133,7 +178,10 @@ class Migration(migrations.Migration): migrations.AddField( model_name='charge', name='account', - field=models.ForeignKey(related_name='charges', null=True, to='djstripe.Account', help_text='The account the charge was made on behalf of. Null here indicates that this value was never set.'), + field=models.ForeignKey( + related_name='charges', null=True, to='djstripe.Account', + help_text='The account the charge was made on behalf of. Null here indicates that this value was \ + never set.'), ), migrations.AddField( model_name='charge', @@ -143,18 +191,27 @@ class Migration(migrations.Migration): migrations.AddField( model_name='charge', name='currency', - field=djstripe.fields.StripeCharField(help_text='Three-letter ISO currency code representing the currency in which the charge was made.', max_length=3, default=''), + field=djstripe.fields.StripeCharField(help_text='Three-letter ISO currency code representing the currency \ + in which the charge was made.', max_length=3, default=''), preserve_default=False, ), migrations.AddField( model_name='charge', name='failure_code', - field=djstripe.fields.StripeCharField(choices=[('invalid_number', 'Invalid Number'), ('invalid_expiry_month', 'Invalid Expiry Month'), ('invalid_expiry_year', 'Invalid Expiry Year'), ('invalid_cvc', 'Invalid Cvc'), ('incorrect_number', 'Incorrect Number'), ('expired_card', 'Expired Card'), ('incorrect_cvc', 'Incorrect Cvc'), ('incorrect_zip', 'Incorrect Zip'), ('card_declined', 'Card Declined'), ('missing', 'Missing'), ('processing_error', 'Processing Error'), ('rate_limit', 'Rate Limit')], max_length=30, help_text='Error code explaining reason for charge failure if available.', null=True), + field=djstripe.fields.StripeCharField( + choices=[('invalid_number', 'Invalid Number'), ('invalid_expiry_month', 'Invalid Expiry Month'), + ('invalid_expiry_year', 'Invalid Expiry Year'), ('invalid_cvc', 'Invalid Cvc'), + ('incorrect_number', 'Incorrect Number'), ('expired_card', 'Expired Card'), + ('incorrect_cvc', 'Incorrect Cvc'), ('incorrect_zip', 'Incorrect Zip'), + ('card_declined', 'Card Declined'), ('missing', 'Missing'), + ('processing_error', 'Processing Error'), ('rate_limit', 'Rate Limit')], + max_length=30, help_text='Error code explaining reason for charge failure if available.', null=True), ), migrations.AddField( model_name='charge', name='failure_message', - field=djstripe.fields.StripeTextField(help_text='Message to user further explaining reason for charge failure if available.', null=True), + field=djstripe.fields.StripeTextField( + help_text='Message to user further explaining reason for charge failure if available.', null=True), ), migrations.AddField( model_name='charge', @@ -164,17 +221,24 @@ class Migration(migrations.Migration): migrations.AddField( model_name='charge', name='fraudulent', - field=djstripe.fields.StripeBooleanField(help_text='Whether or not this charge was marked as fraudulent.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='Whether or not this charge was marked as fraudulent.', default=False), ), migrations.AddField( model_name='charge', name='livemode', - field=djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False), + field=djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False), ), migrations.AddField( model_name='charge', name='metadata', - field=djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True), + field=djstripe.fields.StripeJSONField( + blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for\ + storing additional information about an object in a structured format.', + null=True), ), migrations.AddField( model_name='charge', @@ -189,43 +253,63 @@ class Migration(migrations.Migration): migrations.AddField( model_name='charge', name='source_type', - field=djstripe.fields.StripeCharField(max_length=20, help_text='The payment source type. If the payment source is supported by dj-stripe, a corresponding model is attached to this Charge via a foreign key matching this field.', null=True), + field=djstripe.fields.StripeCharField( + max_length=20, help_text='The payment source type. If the payment source is supported by dj-stripe, \ + a corresponding model is attached to this Charge via a foreign key matching this field.', null=True), ), migrations.AddField( model_name='charge', name='statement_descriptor', - field=djstripe.fields.StripeCharField(max_length=22, help_text='An arbitrary string to be displayed on your customer\'s credit card statement. The statement description may not include <>"\' characters, and will appear on your customer\'s statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.', null=True), + field=djstripe.fields.StripeCharField( + max_length=22, help_text='An arbitrary string to be displayed on your customer\'s credit card \ + statement. The statement description may not include <>"\' characters, and will appear on your \ + customer\'s statement in capital letters. Non-ASCII characters are automatically stripped. While \ + most banks display this information consistently, some may display it incorrectly or not at all.', + null=True), ), migrations.AddField( model_name='charge', name='status', - field=djstripe.fields.StripeCharField(help_text='The status of the payment.', choices=[('succeeded', 'Succeeded'), ('failed', 'Failed')], max_length=10, default='unknown'), + field=djstripe.fields.StripeCharField(help_text='The status of the payment.', + choices=[('succeeded', 'Succeeded'), ('failed', 'Failed')], + max_length=10, default='unknown'), preserve_default=False, ), migrations.AddField( model_name='charge', name='transfer', - field=models.ForeignKey(null=True, to='djstripe.Transfer', help_text='The transfer to the destination account (only applicable if the charge was created using the destination parameter).'), + field=models.ForeignKey(null=True, to='djstripe.Transfer', + help_text='The transfer to the destination account (only applicable if the \ + charge was created using the destination parameter).'), ), migrations.AddField( model_name='customer', name='account_balance', - field=djstripe.fields.StripeIntegerField(help_text="Current balance, if any, being stored on the customer's account. If negative, the customer has credit to apply to the next invoice. If positive, the customer has an amount owed that will be added to the next invoice. The balance does not refer to any unpaid invoices; it solely takes into account amounts that have yet to be successfully applied to any invoice. This balance is only taken into account for recurring charges.", null=True), + field=djstripe.fields.StripeIntegerField(help_text="Current balance, if any, being stored on the \ + customer's account. If negative, the customer has credit to apply to the next invoice. If positive, the \ + customer has an amount owed that will be added to the next invoice. The balance does not refer to any \ + unpaid invoices; it solely takes into account amounts that have yet to be successfully applied to any \ + invoice. This balance is only taken into account for recurring charges.", null=True), ), migrations.AddField( model_name='customer', name='business_vat_id', - field=djstripe.fields.StripeCharField(max_length=20, help_text="The customer's VAT identification number.", null=True), + field=djstripe.fields.StripeCharField(max_length=20, help_text="The customer's VAT identification number.", + null=True), ), migrations.AddField( model_name='customer', name='currency', - field=djstripe.fields.StripeCharField(help_text='The currency the customer can be charged in for recurring billing purposes (subscriptions, invoices, invoice items).', max_length=3, null=True), + field=djstripe.fields.StripeCharField( + help_text='The currency the customer can be charged in for recurring billing purposes \ + (subscriptions, invoices, invoice items).', max_length=3, null=True), ), migrations.AddField( model_name='customer', name='delinquent', - field=djstripe.fields.StripeBooleanField(help_text="Whether or not the latest charge for the customer's latest invoice has failed.", default=False), + field=djstripe.fields.StripeBooleanField( + help_text="Whether or not the latest charge for the customer's latest invoice has failed.", + default=False), ), migrations.AddField( model_name='customer', @@ -235,22 +319,30 @@ class Migration(migrations.Migration): migrations.AddField( model_name='customer', name='livemode', - field=djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False), + field=djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False), ), migrations.AddField( model_name='customer', name='metadata', - field=djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True), + field=djstripe.fields.StripeJSONField( + blank=True, + help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing \ + additional information about an object in a structured format.', null=True), ), migrations.AddField( model_name='customer', name='shipping', - field=djstripe.fields.StripeJSONField(help_text='Shipping information associated with the customer.', null=True), + field=djstripe.fields.StripeJSONField(help_text='Shipping information associated with the customer.', + null=True), ), migrations.AddField( model_name='customer', name='stripe_timestamp', - field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True), + field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', + null=True), ), migrations.AddField( model_name='event', @@ -260,38 +352,59 @@ class Migration(migrations.Migration): migrations.AddField( model_name='event', name='metadata', - field=djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True), + field=djstripe.fields.StripeJSONField( + blank=True, + help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing \ + additional information about an object in a structured format.', null=True), ), migrations.AddField( model_name='event', name='received_api_version', - field=djstripe.fields.StripeCharField(max_length=15, help_text='the API version at which the event data was rendered. Blank for old entries only, all new entries will have this value', blank=True), + field=djstripe.fields.StripeCharField( + max_length=15, + help_text='the API version at which the event data was rendered. Blank for old entries only, all \ + new entries will have this value', blank=True), ), migrations.AddField( model_name='event', name='request_id', - field=djstripe.fields.StripeCharField(max_length=50, help_text="Information about the request that triggered this event, for traceability purposes. If empty string then this is an old entry without that data. If Null then this is not an old entry, but a Stripe 'automated' event with no associated request.", blank=True, null=True), + field=djstripe.fields.StripeCharField( + max_length=50, + help_text="Information about the request that triggered this event, for traceability purposes. \ + If empty string then this is an old entry without that data. If Null then this is not an old entry, \ + but a Stripe 'automated' event with no associated request.", blank=True, null=True), ), migrations.AddField( model_name='event', name='stripe_timestamp', - field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True), + field=djstripe.fields.StripeDateTimeField( + help_text='The datetime this object was created in stripe.', null=True), ), migrations.AddField( model_name='invoice', name='amount_due', - field=djstripe.fields.StripeCurrencyField(help_text="Final amount due at this time for this invoice. If the invoice's total is smaller than the minimum charge amount, for example, or if there is account credit that can be applied to the invoice, the amount_due may be 0. If there is a positive starting_balance for the invoice (the customer owes money), the amount_due will also take that into account. The charge that gets generated for the invoice will be for the amount specified in amount_due.", max_digits=7, default=0, decimal_places=2), + field=djstripe.fields.StripeCurrencyField( + help_text="Final amount due at this time for this invoice. If the invoice's total is smaller than \ + the minimum charge amount, for example, or if there is account credit that can be applied to the \ + invoice, the amount_due may be 0. If there is a positive starting_balance for the invoice \ + (the customer owes money), the amount_due will also take that into account. The charge that gets \ + generated for the invoice will be for the amount specified in amount_due.", + max_digits=7, default=0, decimal_places=2), preserve_default=False, ), migrations.AddField( model_name='invoice', name='application_fee', - field=djstripe.fields.StripeCurrencyField(max_digits=7, help_text="The fee in cents that will be applied to the invoice and transferred to the application owner's Stripe account when the invoice is paid.", decimal_places=2, null=True), + field=djstripe.fields.StripeCurrencyField( + max_digits=7, + help_text="The fee in cents that will be applied to the invoice and transferred to the application \ + owner's Stripe account when the invoice is paid.", decimal_places=2, null=True), ), migrations.AddField( model_name='invoice', name='currency', - field=djstripe.fields.StripeCharField(help_text='Three-letter ISO currency code.', max_length=3, default=''), + field=djstripe.fields.StripeCharField(help_text='Three-letter ISO currency code.', + max_length=3, default=''), preserve_default=False, ), migrations.AddField( @@ -302,100 +415,152 @@ class Migration(migrations.Migration): migrations.AddField( model_name='invoice', name='ending_balance', - field=djstripe.fields.StripeIntegerField(help_text='Ending customer balance after attempting to pay invoice. If the invoice has not been attempted yet, this will be null.', null=True), + field=djstripe.fields.StripeIntegerField( + help_text='Ending customer balance after attempting to pay invoice. If the invoice has not been \ + attempted yet, this will be null.', null=True), ), migrations.AddField( model_name='invoice', name='forgiven', - field=djstripe.fields.StripeBooleanField(help_text='Whether or not the invoice has been forgiven. Forgiving an invoice instructs us to update the subscription status as if the invoice were successfully paid. Once an invoice has been forgiven, it cannot be unforgiven or reopened.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='Whether or not the invoice has been forgiven. Forgiving an invoice instructs us to \ + update the subscription status as if the invoice were successfully paid. Once an invoice has been \ + forgiven, it cannot be unforgiven or reopened.', default=False), ), migrations.AddField( model_name='invoice', name='livemode', - field=djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False), + field=djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False), ), migrations.AddField( model_name='invoice', name='metadata', - field=djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True), + field=djstripe.fields.StripeJSONField( + blank=True, + help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing \ + additional information about an object in a structured format.', + null=True), ), migrations.AddField( model_name='invoice', name='next_payment_attempt', - field=djstripe.fields.StripeDateTimeField(help_text='The time at which payment will next be attempted.', null=True), + field=djstripe.fields.StripeDateTimeField(help_text='The time at which payment will next be attempted.', + null=True), ), migrations.AddField( model_name='invoice', name='starting_balance', - field=djstripe.fields.StripeIntegerField(help_text='Starting customer balance before attempting to pay invoice. If the invoice has not been attempted yet, this will be the current customer balance.', default=0), + field=djstripe.fields.StripeIntegerField( + help_text='Starting customer balance before attempting to pay invoice. If the invoice has not been \ + attempted yet, this will be the current customer balance.', default=0), preserve_default=False, ), migrations.AddField( model_name='invoice', name='statement_descriptor', - field=djstripe.fields.StripeCharField(max_length=22, help_text='An arbitrary string to be displayed on your customer\'s credit card statement. The statement description may not include <>"\' characters, and will appear on your customer\'s statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.', null=True), + field=djstripe.fields.StripeCharField( + max_length=22, + help_text='An arbitrary string to be displayed on your customer\'s credit card statement. \ + The statement description may not include <>"\' characters, and will appear on your customer\'s \ + statement in capital letters. Non-ASCII characters are automatically stripped. While most banks \ + display this information consistently, some may display it incorrectly or not at all.', null=True), ), migrations.AddField( model_name='invoice', name='stripe_timestamp', - field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True), + field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', + null=True), ), migrations.AddField( model_name='invoice', name='subscription', - field=models.ForeignKey(related_name='invoices', null=True, to='djstripe.Subscription', help_text='The subscription that this invoice was prepared for, if any.'), + field=models.ForeignKey( + related_name='invoices', + null=True, + to='djstripe.Subscription', + help_text='The subscription that this invoice was prepared for, if any.'), ), migrations.AddField( model_name='invoice', name='subscription_proration_date', - field=djstripe.fields.StripeDateTimeField(help_text='Only set for upcoming invoices that preview prorations. The time used to calculate prorations.', null=True), + field=djstripe.fields.StripeDateTimeField( + help_text='Only set for upcoming invoices that preview prorations. The time used to calculate \ + prorations.', + null=True), ), migrations.AddField( model_name='invoice', name='tax', - field=djstripe.fields.StripeCurrencyField(max_digits=7, help_text='The amount of tax included in the total, calculated from ``tax_percent`` and the subtotal. If no ``tax_percent`` is defined, this value will be null.', decimal_places=2, null=True), + field=djstripe.fields.StripeCurrencyField(max_digits=7, help_text='The amount of tax included in the \ + total, calculated from ``tax_percent`` and the subtotal. If no ``tax_percent`` is defined, this value \ + will be null.', decimal_places=2, null=True), ), migrations.AddField( model_name='invoice', name='tax_percent', - field=djstripe.fields.StripePercentField(validators=[django.core.validators.MinValueValidator(1.0), django.core.validators.MaxValueValidator(100.0)], max_digits=5, help_text="This percentage of the subtotal has been added to the total amount of the invoice, including invoice line items and discounts. This field is inherited from the subscription's ``tax_percent`` field, but can be changed before the invoice is paid. This field defaults to null.", decimal_places=2, null=True), + field=djstripe.fields.StripePercentField( + validators=[django.core.validators.MinValueValidator(1.0), + django.core.validators.MaxValueValidator(100.0)], + max_digits=5, + help_text="This percentage of the subtotal has been added to the total amount of the invoice, \ + including invoice line items and discounts. This field is inherited from the subscription's \ + ``tax_percent`` field, but can be changed before the invoice is paid. This field defaults to null.", + decimal_places=2, null=True), ), migrations.AddField( model_name='invoiceitem', name='customer', - field=models.ForeignKey(related_name='invoiceitems', default=1, to='djstripe.Customer', help_text='The customer associated with this invoiceitem.'), + field=models.ForeignKey(related_name='invoiceitems', default=1, to='djstripe.Customer', + help_text='The customer associated with this invoiceitem.'), preserve_default=False, ), migrations.AddField( model_name='invoiceitem', name='date', - field=djstripe.fields.StripeDateTimeField(help_text='The date on the invoiceitem.', default=datetime.datetime(2100, 1, 1, 0, 0)), + field=djstripe.fields.StripeDateTimeField(help_text='The date on the invoiceitem.', + default=datetime.datetime(2100, 1, 1, 0, 0, + tzinfo=django.utils.timezone.utc)), preserve_default=False, ), migrations.AddField( model_name='invoiceitem', name='discountable', - field=djstripe.fields.StripeBooleanField(help_text='If True, discounts will apply to this invoice item. Always False for prorations.', default=False), + field=djstripe.fields.StripeBooleanField(help_text='If True, discounts will apply to this invoice item. \ + Always False for prorations.', default=False), ), migrations.AddField( model_name='invoiceitem', name='livemode', - field=djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False), + field=djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False), ), migrations.AddField( model_name='invoiceitem', name='metadata', - field=djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True), + field=djstripe.fields.StripeJSONField( + blank=True, + help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing \ + additional information about an object in a structured format.', null=True), ), migrations.AddField( model_name='invoiceitem', name='stripe_timestamp', - field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True), + field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', + null=True), ), migrations.AddField( model_name='invoiceitem', name='subscription', - field=models.ForeignKey(related_name='invoiceitems', null=True, to='djstripe.Subscription', help_text='The subscription that this invoice item has been created for, if any.'), + field=models.ForeignKey( + related_name='invoiceitems', + null=True, + to='djstripe.Subscription', + help_text='The subscription that this invoice item has been created for, if any.'), ), migrations.AddField( model_name='plan', @@ -405,22 +570,34 @@ class Migration(migrations.Migration): migrations.AddField( model_name='plan', name='livemode', - field=djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False), + field=djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False), ), migrations.AddField( model_name='plan', name='metadata', - field=djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True), + field=djstripe.fields.StripeJSONField( + blank=True, + help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing \ + additional information about an object in a structured format.', null=True), ), migrations.AddField( model_name='plan', name='statement_descriptor', - field=djstripe.fields.StripeCharField(max_length=22, help_text='An arbitrary string to be displayed on your customer\'s credit card statement. The statement description may not include <>"\' characters, and will appear on your customer\'s statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.', null=True), + field=djstripe.fields.StripeCharField( + max_length=22, + help_text='An arbitrary string to be displayed on your customer\'s credit card statement. The \ + statement description may not include <>"\' characters, and will appear on your customer\'s statement \ + in capital letters. Non-ASCII characters are automatically stripped. While most banks display this \ + information consistently, some may display it incorrectly or not at all.', null=True), ), migrations.AddField( model_name='plan', name='stripe_timestamp', - field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True), + field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', + null=True), ), migrations.AlterModelOptions( name='plan', @@ -429,7 +606,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='subscription', name='application_fee_percent', - field=djstripe.fields.StripePercentField(validators=[django.core.validators.MinValueValidator(1.0), django.core.validators.MaxValueValidator(100.0)], help_text='A positive decimal that represents the fee percentage of the subscription invoice amount that will be transferred to the application owner’s Stripe account each billing period.', max_digits=5, decimal_places=2, null=True), + field=djstripe.fields.StripePercentField( + validators=[django.core.validators.MinValueValidator(1.0), + django.core.validators.MaxValueValidator(100.0)], + help_text='A positive decimal that represents the fee percentage of the subscription invoice amount \ + that will be transferred to the application owner’s Stripe account each billing period.', + max_digits=5, decimal_places=2, null=True), ), migrations.AddField( model_name='subscription', @@ -439,12 +621,18 @@ class Migration(migrations.Migration): migrations.AddField( model_name='subscription', name='livemode', - field=djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False), + field=djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False), ), migrations.AddField( model_name='subscription', name='metadata', - field=djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True), + field=djstripe.fields.StripeJSONField( + blank=True, + help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing \ + additional information about an object in a structured format.', null=True), ), migrations.AddField( model_name='subscription', @@ -455,50 +643,80 @@ class Migration(migrations.Migration): migrations.AddField( model_name='subscription', name='stripe_timestamp', - field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True), + field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', + null=True), ), migrations.AddField( model_name='subscription', name='tax_percent', - field=djstripe.fields.StripePercentField(validators=[django.core.validators.MinValueValidator(1.0), django.core.validators.MaxValueValidator(100.0)], max_digits=5, help_text='A positive decimal (with at most two decimal places) between 1 and 100. This represents the percentage of the subscription invoice subtotal that will be calculated and added as tax to the final amount each billing period.', decimal_places=2, null=True), + field=djstripe.fields.StripePercentField( + validators=[django.core.validators.MinValueValidator(1.0), + django.core.validators.MaxValueValidator(100.0)], + max_digits=5, + help_text='A positive decimal (with at most two decimal places) between 1 and 100. This represents \ + the percentage of the subscription invoice subtotal that will be calculated and added as tax to the \ + final amount each billing period.', decimal_places=2, null=True), ), migrations.AddField( model_name='transfer', name='amount_reversed', - field=djstripe.fields.StripeCurrencyField(max_digits=7, help_text='The amount reversed (can be less than the amount attribute on the transfer if a partial reversal was issued).', decimal_places=2, null=True), + field=djstripe.fields.StripeCurrencyField( + max_digits=7, + help_text='The amount reversed (can be less than the amount attribute on the transfer if a partial \ + reversal was issued).', decimal_places=2, null=True), ), migrations.AddField( model_name='transfer', name='currency', - field=djstripe.fields.StripeCharField(help_text='Three-letter ISO currency code.', max_length=3, default=''), + field=djstripe.fields.StripeCharField(help_text='Three-letter ISO currency code.', + max_length=3, default=''), preserve_default=False, ), migrations.AddField( model_name='transfer', name='destination', - field=djstripe.fields.StripeIdField(help_text='ID of the bank account, card, or Stripe account the transfer was sent to.', max_length=50, default='unknown'), + field=djstripe.fields.StripeIdField( + help_text='ID of the bank account, card, or Stripe account the transfer was sent to.', + max_length=50, default='unknown'), preserve_default=False, ), migrations.AddField( model_name='transfer', name='destination_payment', - field=djstripe.fields.StripeIdField(max_length=50, help_text='If the destination is a Stripe account, this will be the ID of the payment that the destination account received for the transfer.', null=True), + field=djstripe.fields.StripeIdField( + max_length=50, + help_text='If the destination is a Stripe account, this will be the ID of the payment that the \ + destination account received for the transfer.', null=True), ), migrations.AddField( model_name='transfer', name='destination_type', - field=djstripe.fields.StripeCharField(help_text='The type of the transfer destination.', choices=[('card', 'Card'), ('bank_account', 'Bank Account'), ('stripe_account', 'Stripe Account')], max_length=14, default='unknown'), + field=djstripe.fields.StripeCharField( + help_text='The type of the transfer destination.', + choices=[('card', 'Card'), ('bank_account', 'Bank Account'), ('stripe_account', 'Stripe Account')], + max_length=14, default='unknown'), preserve_default=False, ), migrations.AddField( model_name='transfer', name='failure_code', - field=djstripe.fields.StripeCharField(choices=[('insufficient_funds', 'Insufficient Funds'), ('account_closed', 'Account Closed'), ('no_account', 'No Account'), ('invalid_account_number', 'Invalid Account Number'), ('debit_not_authorized', 'Debit Not Authorized'), ('bank_ownership_changed', 'Bank Ownership Changed'), ('account_frozen', 'Account Frozen'), ('could_not_process', 'Could Not Process'), ('bank_account_restricted', 'Bank Account Restricted'), ('invalid_currency', 'Invalid Currency')], max_length=23, help_text='Error code explaining reason for transfer failure if available. See https://stripe.com/docs/api/python#transfer_failures.', null=True), + field=djstripe.fields.StripeCharField( + choices=[('insufficient_funds', 'Insufficient Funds'), ('account_closed', 'Account Closed'), + ('no_account', 'No Account'), ('invalid_account_number', 'Invalid Account Number'), + ('debit_not_authorized', 'Debit Not Authorized'), + ('bank_ownership_changed', 'Bank Ownership Changed'), ('account_frozen', 'Account Frozen'), + ('could_not_process', 'Could Not Process'), + ('bank_account_restricted', 'Bank Account Restricted'), + ('invalid_currency', 'Invalid Currency')], + max_length=23, + help_text='Error code explaining reason for transfer failure if available. See \ + https://stripe.com/docs/api/python#transfer_failures.', null=True), ), migrations.AddField( model_name='transfer', name='failure_message', - field=djstripe.fields.StripeTextField(help_text='Message to user further explaining reason for transfer failure if available.', null=True), + field=djstripe.fields.StripeTextField( + help_text='Message to user further explaining reason for transfer failure if available.', null=True), ), migrations.AddField( model_name='transfer', @@ -513,38 +731,58 @@ class Migration(migrations.Migration): migrations.AddField( model_name='transfer', name='livemode', - field=djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False), + field=djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False), ), migrations.AddField( model_name='transfer', name='metadata', - field=djstripe.fields.StripeJSONField(blank=True, help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.', null=True), + field=djstripe.fields.StripeJSONField( + blank=True, + help_text='A set of key/value pairs that you can attach to an object. It can be useful for storing \ + additional information about an object in a structured format.', null=True), ), migrations.AddField( model_name='transfer', name='reversed', - field=djstripe.fields.StripeBooleanField(help_text='Whether or not the transfer has been fully reversed. If the transfer is only partially reversed, this attribute will still be false.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='Whether or not the transfer has been fully reversed. If the transfer is only partially \ + reversed, this attribute will still be false.', default=False), ), migrations.AddField( model_name='transfer', name='source_transaction', - field=djstripe.fields.StripeIdField(max_length=50, help_text='ID of the charge (or other transaction) that was used to fund the transfer. If null, the transfer was funded from the available balance.', null=True), + field=djstripe.fields.StripeIdField( + max_length=50, + help_text='ID of the charge (or other transaction) that was used to fund the transfer. If null, the \ + transfer was funded from the available balance.', null=True), ), migrations.AddField( model_name='transfer', name='source_type', - field=djstripe.fields.StripeCharField(help_text='The source balance from which this transfer came.', choices=[('card', 'Card'), ('bank_account', 'Bank Account'), ('bitcoin_reciever', 'Bitcoin Reciever'), ('alipay_account', 'Alipay Account')], max_length=16, default='unknown'), + field=djstripe.fields.StripeCharField( + help_text='The source balance from which this transfer came.', + choices=[('card', 'Card'), ('bank_account', 'Bank Account'), ('bitcoin_reciever', 'Bitcoin Reciever'), + ('alipay_account', 'Alipay Account')], max_length=16, default='unknown'), preserve_default=False, ), migrations.AddField( model_name='transfer', name='statement_descriptor', - field=djstripe.fields.StripeCharField(max_length=22, help_text='An arbitrary string to be displayed on your customer\'s credit card statement. The statement description may not include <>"\' characters, and will appear on your customer\'s statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.', null=True), + field=djstripe.fields.StripeCharField( + max_length=22, + help_text='An arbitrary string to be displayed on your customer\'s credit card statement. The \ + statement description may not include <>"\' characters, and will appear on your customer\'s statement \ + in capital letters. Non-ASCII characters are automatically stripped. While most banks display this \ + information consistently, some may display it incorrectly or not at all.', null=True), ), migrations.AddField( model_name='transfer', name='stripe_timestamp', - field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True), + field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', + null=True), ), migrations.AddField( model_name='stripesource', @@ -554,7 +792,8 @@ class Migration(migrations.Migration): migrations.AddField( model_name='stripesource', name='polymorphic_ctype', - field=models.ForeignKey(related_name='polymorphic_djstripe.stripesource_set+', to='contenttypes.ContentType', editable=False, null=True), + field=models.ForeignKey(related_name='polymorphic_djstripe.stripesource_set+', + to='contenttypes.ContentType', editable=False, null=True), ), migrations.AddField( model_name='customer', diff --git a/djstripe/migrations/0010_splitting_up_adds_from_alters.py b/djstripe/migrations/0010_splitting_up_adds_from_alters.py index 8ca9d56970..0a1fe167cc 100644 --- a/djstripe/migrations/0010_splitting_up_adds_from_alters.py +++ b/djstripe/migrations/0010_splitting_up_adds_from_alters.py @@ -1,9 +1,12 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import datetime + from django.db import migrations, models +from django.utils import timezone + import djstripe.fields -import datetime class Migration(migrations.Migration): @@ -23,17 +26,25 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='event', name='customer', - field=models.ForeignKey(null=True, to='djstripe.Customer', help_text='In the event that there is a related customer, this will point to that Customer record'), + field=models.ForeignKey( + null=True, + to='djstripe.Customer', + help_text='In the event that there is a related customer, this will point to that Customer record'), ), migrations.AlterField( model_name='event', name='livemode', - field=djstripe.fields.StripeNullBooleanField(help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, this field indicates whether this record comes from Stripe test mode or live mode operation.', default=False), + field=djstripe.fields.StripeNullBooleanField( + help_text='Null here indicates that the livemode status is unknown or was previously unrecorded. \ + Otherwise, this field indicates whether this record comes from Stripe test mode or live mode \ + operation.', default=False), ), migrations.AlterField( model_name='event', name='processed', - field=models.BooleanField(help_text='If validity is performed, webhook event processor(s) may run to take further action on the event. Once these have run, this is set to True.', default=False), + field=models.BooleanField( + help_text='If validity is performed, webhook event processor(s) may run to take further action on \ + the event. Once these have run, this is set to True.', default=False), ), migrations.AlterField( model_name='event', @@ -48,27 +59,40 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='event', name='valid', - field=models.NullBooleanField(help_text='Tri-state bool. Null == validity not yet confirmed. Otherwise, this field indicates that this event was checked via stripe api and found to be either authentic (valid=True) or in-authentic (possibly malicious)'), + field=models.NullBooleanField( + help_text='Tri-state bool. Null == validity not yet confirmed. Otherwise, this field indicates that \ + this event was checked via stripe api and found to be either authentic (valid=True) or in-authentic \ + (possibly malicious)'), ), migrations.AlterField( model_name='event', name='webhook_message', - field=djstripe.fields.StripeJSONField(help_text='data received at webhook. data should be considered to be garbage until validity check is run and valid flag is set'), + field=djstripe.fields.StripeJSONField( + help_text='data received at webhook. data should be considered to be garbage until validity check is \ + run and valid flag is set'), ), migrations.AlterField( model_name='invoice', name='attempt_count', - field=djstripe.fields.StripeIntegerField(help_text='Number of payment attempts made for this invoice, from the perspective of the payment retry schedule. Any payment attempt counts as the first attempt, and subsequently only automatic retries increment the attempt count. In other words, manual payment attempts after the first attempt do not affect the retry schedule.', default=0), + field=djstripe.fields.StripeIntegerField( + help_text='Number of payment attempts made for this invoice, from the perspective of the payment \ + retry schedule. Any payment attempt counts as the first attempt, and subsequently only automatic \ + retries increment the attempt count. In other words, manual payment attempts after the first attempt \ + do not affect the retry schedule.', default=0), preserve_default=False, ), migrations.AlterField( model_name='invoice', name='attempted', - field=djstripe.fields.StripeBooleanField(help_text='Whether or not an attempt has been made to pay the invoice. An invoice is not attempted until 1 hour after the ``invoice.created`` webhook, for example, so you might not want to display that invoice as unpaid to your users.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='Whether or not an attempt has been made to pay the invoice. An invoice is not attempted \ + until 1 hour after the ``invoice.created`` webhook, for example, so you might not want to display \ + that invoice as unpaid to your users.', default=False), ), - # Original format is a charge stripe id.... renaming it and creating a new field. The sync in the next migration will take care of filling the charge field. + # Original format is a charge stripe id.... renaming it and creating a new field. + # The sync in the next migration will take care of filling the charge field. migrations.RenameField( model_name='invoice', old_name='charge', @@ -82,18 +106,23 @@ class Migration(migrations.Migration): migrations.AddField( model_name='invoice', name='charge', - field=models.OneToOneField(to='djstripe.Charge', related_name='invoice', null=True, help_text='The latest charge generated for this invoice, if any.'), + field=models.OneToOneField(to='djstripe.Charge', related_name='invoice', null=True, + help_text='The latest charge generated for this invoice, if any.'), ), migrations.AlterField( model_name='invoice', name='closed', - field=djstripe.fields.StripeBooleanField(help_text="Whether or not the invoice is still trying to collect payment. An invoice is closed if it's either paid or it has been marked closed. A closed invoice will no longer attempt to collect payment.", default=False), + field=djstripe.fields.StripeBooleanField( + help_text="Whether or not the invoice is still trying to collect payment. An invoice is closed if \ + it's either paid or it has been marked closed. A closed invoice will no longer attempt to collect \ + payment.", default=False), ), migrations.AlterField( model_name='invoice', name='customer', - field=models.ForeignKey(related_name='invoices', to='djstripe.Customer', help_text='The customer associated with this invoice.'), + field=models.ForeignKey(related_name='invoices', to='djstripe.Customer', + help_text='The customer associated with this invoice.'), ), migrations.AlterField( model_name='invoice', @@ -103,17 +132,20 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='invoice', name='paid', - field=djstripe.fields.StripeBooleanField(help_text='The time at which payment will next be attempted.', default=False), + field=djstripe.fields.StripeBooleanField(help_text='The time at which payment will next be attempted.', + default=False), ), migrations.AlterField( model_name='invoice', name='period_end', - field=djstripe.fields.StripeDateTimeField(help_text='End of the usage period during which invoice items were added to this invoice.'), + field=djstripe.fields.StripeDateTimeField( + help_text='End of the usage period during which invoice items were added to this invoice.'), ), migrations.AlterField( model_name='invoice', name='period_start', - field=djstripe.fields.StripeDateTimeField(help_text='Start of the usage period during which invoice items were added to this invoice.'), + field=djstripe.fields.StripeDateTimeField( + help_text='Start of the usage period during which invoice items were added to this invoice.'), ), migrations.AlterField( model_name='invoice', @@ -123,12 +155,17 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='invoice', name='subtotal', - field=djstripe.fields.StripeCurrencyField(max_digits=7, help_text='Only set for upcoming invoices that preview prorations. The time used to calculate prorations.', decimal_places=2), + field=djstripe.fields.StripeCurrencyField( + max_digits=7, + help_text='Only set for upcoming invoices that preview prorations. \ + The time used to calculate prorations.', + decimal_places=2), ), migrations.AlterField( model_name='invoice', name='total', - field=djstripe.fields.StripeCurrencyField(max_digits=7, decimal_places=2, verbose_name='Total after discount.'), + field=djstripe.fields.StripeCurrencyField(max_digits=7, decimal_places=2, + verbose_name='Total after discount.'), ), migrations.AlterField( model_name='invoiceitem', @@ -148,20 +185,24 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='invoiceitem', name='invoice', - field=models.ForeignKey(related_name='invoiceitems', to='djstripe.Invoice', help_text='The invoice to which this invoiceitem is attached.'), + field=models.ForeignKey(related_name='invoiceitems', to='djstripe.Invoice', + help_text='The invoice to which this invoiceitem is attached.'), ), migrations.AlterField( model_name='invoiceitem', name='period_end', - field=djstripe.fields.StripeDateTimeField(help_text="Might be the date when this invoiceitem's invoice was sent."), + field=djstripe.fields.StripeDateTimeField( + help_text="Might be the date when this invoiceitem's invoice was sent."), ), migrations.AlterField( model_name='invoiceitem', name='period_start', - field=djstripe.fields.StripeDateTimeField(help_text='Might be the date when this invoiceitem was added to the invoice'), + field=djstripe.fields.StripeDateTimeField( + help_text='Might be the date when this invoiceitem was added to the invoice'), ), - # Original format is a charge stripe id.... renaming it and creating a new field. The sync in the next migration will take care of filling the charge field. + # Original format is a charge stripe id.... renaming it and creating a new field. + # The sync in the next migration will take care of filling the charge field. migrations.RenameField( model_name='invoiceitem', old_name="plan", @@ -175,18 +216,27 @@ class Migration(migrations.Migration): migrations.AddField( model_name='invoiceitem', name='plan', - field=models.ForeignKey(related_name='invoiceitems', null=True, to='djstripe.Plan', help_text='If the invoice item is a proration, the plan of the subscription for which the proration was computed.'), + field=models.ForeignKey( + related_name='invoiceitems', + null=True, + to='djstripe.Plan', + help_text='If the invoice item is a proration, the plan of the subscription for which the \ + proration was computed.'), ), migrations.AlterField( model_name='invoiceitem', name='proration', - field=djstripe.fields.StripeBooleanField(help_text='Whether or not the invoice item was created automatically as a proration adjustment when the customer switched plans.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='Whether or not the invoice item was created automatically as a proration adjustment when \ + the customer switched plans.', default=False), ), migrations.AlterField( model_name='invoiceitem', name='quantity', - field=djstripe.fields.StripeIntegerField(help_text='If the invoice item is a proration, the quantity of the subscription for which the proration was computed.', null=True), + field=djstripe.fields.StripeIntegerField( + help_text='If the invoice item is a proration, the quantity of the subscription for which the \ + proration was computed.', null=True), ), # InvoiceItems stripe_id was the subscription stripe_id... what @@ -209,7 +259,10 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='plan', name='amount', - field=djstripe.fields.StripeCurrencyField(max_digits=7, help_text='Amount to be charged on the interval specified.', decimal_places=2), + field=djstripe.fields.StripeCurrencyField( + max_digits=7, + help_text='Amount to be charged on the interval specified.', + decimal_places=2), ), migrations.AlterField( model_name='plan', @@ -219,17 +272,23 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='plan', name='interval', - field=djstripe.fields.StripeCharField(choices=[('day', 'Day'), ('week', 'Week'), ('month', 'Month'), ('year', 'Year')], max_length=5, help_text='The frequency with which a subscription should be billed.'), + field=djstripe.fields.StripeCharField( + choices=[('day', 'Day'), ('week', 'Week'), ('month', 'Month'), ('year', 'Year')], + max_length=5, + help_text='The frequency with which a subscription should be billed.'), ), migrations.AlterField( model_name='plan', name='interval_count', - field=djstripe.fields.StripeIntegerField(help_text='The number of intervals (specified in the interval property) between each subscription billing.', null=True), + field=djstripe.fields.StripeIntegerField( + help_text='The number of intervals (specified in the interval property) between each \ + subscription billing.', null=True), ), migrations.AlterField( model_name='plan', name='name', - field=djstripe.fields.StripeTextField(help_text='Name of the plan, to be displayed on invoices and in the web interface.'), + field=djstripe.fields.StripeTextField( + help_text='Name of the plan, to be displayed on invoices and in the web interface.'), ), migrations.AlterField( model_name='plan', @@ -239,44 +298,63 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='plan', name='trial_period_days', - field=djstripe.fields.StripeIntegerField(help_text='Number of trial period days granted when subscribing a customer to this plan. Null if the plan has no trial period.', null=True), + field=djstripe.fields.StripeIntegerField( + help_text='Number of trial period days granted when subscribing a customer to this plan. \ + Null if the plan has no trial period.', null=True), ), migrations.AlterField( model_name='subscription', name='cancel_at_period_end', - field=djstripe.fields.StripeBooleanField(help_text='If the subscription has been canceled with the ``at_period_end`` flag set to true, ``cancel_at_period_end`` on the subscription will be true. You can use this attribute to determine whether a subscription that has a status of active is scheduled to be canceled at the end of the current period.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='If the subscription has been canceled with the ``at_period_end`` flag set to true, \ + ``cancel_at_period_end`` on the subscription will be true. You can use this attribute to determine \ + whether a subscription that has a status of active is scheduled to be canceled at the end of the \ + current period.', default=False), ), migrations.AlterField( model_name='subscription', name='canceled_at', - field=djstripe.fields.StripeDateTimeField(help_text='If the subscription has been canceled, the date of that cancellation. If the subscription was canceled with ``cancel_at_period_end``, canceled_at will still reflect the date of the initial cancellation request, not the end of the subscription period when the subscription is automatically moved to a canceled state.', null=True), + field=djstripe.fields.StripeDateTimeField( + help_text='If the subscription has been canceled, the date of that cancellation. \ + If the subscription was canceled with ``cancel_at_period_end``, canceled_at will still reflect the \ + date of the initial cancellation request, not the end of the subscription period when the \ + subscription is automatically moved to a canceled state.', null=True), ), migrations.AlterField( model_name='subscription', name='current_period_end', - field=djstripe.fields.StripeDateTimeField(help_text='End of the current period for which the subscription has been invoiced. At the end of this period, a new invoice will be created.', default=datetime.datetime(2100, 1, 1, 0, 0)), + field=djstripe.fields.StripeDateTimeField( + help_text='End of the current period for which the subscription has been invoiced. At the end of \ + this period, a new invoice will be created.', default=datetime.datetime(2100, 1, 1, 0, 0, + tzinfo=timezone.utc)), preserve_default=False, ), migrations.AlterField( model_name='subscription', name='current_period_start', - field=djstripe.fields.StripeDateTimeField(help_text='Start of the current period for which the subscription has been invoiced.', default=datetime.datetime(2100, 1, 1, 0, 0)), + field=djstripe.fields.StripeDateTimeField( + help_text='Start of the current period for which the subscription has been invoiced.', + default=datetime.datetime(2100, 1, 1, 0, 0, tzinfo=timezone.utc)), preserve_default=False, ), migrations.AlterField( model_name='subscription', name='customer', - field=models.ForeignKey(related_name='subscriptions', default=1, to='djstripe.Customer', help_text='The customer associated with this subscription.'), + field=models.ForeignKey(related_name='subscriptions', default=1, to='djstripe.Customer', + help_text='The customer associated with this subscription.'), preserve_default=False, ), migrations.AlterField( model_name='subscription', name='ended_at', - field=djstripe.fields.StripeDateTimeField(help_text='If the subscription has ended (either because it was canceled or because the customer was switched to a subscription to a new plan), the date the subscription ended.', null=True), + field=djstripe.fields.StripeDateTimeField( + help_text='If the subscription has ended (either because it was canceled or because the customer \ + was switched to a subscription to a new plan), the date the subscription ended.', null=True), ), - # Original format is a charge stripe id.... renaming it and creating a new field. The sync in the next migration will take care of filling the charge field. + # Original format is a charge stripe id.... renaming it and creating a new field. + # The sync in the next migration will take care of filling the charge field. migrations.RenameField( model_name='subscription', old_name="plan", @@ -290,7 +368,8 @@ class Migration(migrations.Migration): migrations.AddField( model_name='subscription', name='plan', - field=models.ForeignKey(related_name='subscriptions', default=1, to='djstripe.Plan', help_text='The plan associated with this subscription.'), + field=models.ForeignKey(related_name='subscriptions', default=1, to='djstripe.Plan', + help_text='The plan associated with this subscription.'), preserve_default=False, ), @@ -307,17 +386,22 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='subscription', name='status', - field=djstripe.fields.StripeCharField(choices=[('trialing', 'Trialing'), ('active', 'Active'), ('past_due', 'Past Due'), ('canceled', 'Canceled'), ('unpaid', 'Unpaid')], max_length=8, help_text='The status of this subscription.'), + field=djstripe.fields.StripeCharField( + choices=[('trialing', 'Trialing'), ('active', 'Active'), ('past_due', 'Past Due'), + ('canceled', 'Canceled'), ('unpaid', 'Unpaid')], + max_length=8, help_text='The status of this subscription.'), ), migrations.AlterField( model_name='subscription', name='trial_end', - field=djstripe.fields.StripeDateTimeField(help_text='If the subscription has a trial, the end of that trial.', null=True), + field=djstripe.fields.StripeDateTimeField( + help_text='If the subscription has a trial, the end of that trial.', null=True), ), migrations.AlterField( model_name='subscription', name='trial_start', - field=djstripe.fields.StripeDateTimeField(help_text='If the subscription has a trial, the beginning of that trial.', null=True), + field=djstripe.fields.StripeDateTimeField( + help_text='If the subscription has a trial, the beginning of that trial.', null=True), ), migrations.AlterField( @@ -338,7 +422,8 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='transfer', name='amount', - field=djstripe.fields.StripeCurrencyField(max_digits=7, help_text='The amount transferred', decimal_places=2), + field=djstripe.fields.StripeCurrencyField(max_digits=7, help_text='The amount transferred', + decimal_places=2), ), migrations.AlterField( model_name='transfer', @@ -368,7 +453,9 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='transfer', name='date', - field=djstripe.fields.StripeDateTimeField(help_text="Date the transfer is scheduled to arrive in the bank. This doesn't factor in delays like weekends or bank holidays."), + field=djstripe.fields.StripeDateTimeField( + help_text="Date the transfer is scheduled to arrive in the bank. \ + This doesn't factor in delays like weekends or bank holidays."), ), migrations.AlterField( model_name='transfer', @@ -398,7 +485,13 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='transfer', name='status', - field=djstripe.fields.StripeCharField(choices=[('paid', 'Paid'), ('pending', 'Pending'), ('in_transit', 'In Transit'), ('canceled', 'Canceled'), ('failed', 'Failed')], max_length=10, help_text='The current status of the transfer. A transfer will be pending until it is submitted to the bank, at which point it becomes in_transit. It will then change to paid if the transaction goes through. If it does not go through successfully, its status will change to failed or canceled.'), + field=djstripe.fields.StripeCharField( + choices=[('paid', 'Paid'), ('pending', 'Pending'), ('in_transit', 'In Transit'), + ('canceled', 'Canceled'), ('failed', 'Failed')], + max_length=10, + help_text='The current status of the transfer. A transfer will be pending until it is submitted to \ + the bank, at which point it becomes in_transit. It will then change to paid if the transaction goes \ + through. If it does not go through successfully, its status will change to failed or canceled.'), ), migrations.AlterField( model_name='transfer', @@ -419,19 +512,23 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='charge', name='amount', - field=djstripe.fields.StripeCurrencyField(help_text='Amount charged.', max_digits=7, default=0, decimal_places=2), + field=djstripe.fields.StripeCurrencyField(help_text='Amount charged.', max_digits=7, default=0, + decimal_places=2), preserve_default=False, ), migrations.AlterField( model_name='charge', name='amount_refunded', - field=djstripe.fields.StripeCurrencyField(help_text='Amount refunded (can be less than the amount attribute on the charge if a partial refund was issued).', max_digits=7, default=0, decimal_places=2), + field=djstripe.fields.StripeCurrencyField( + help_text='Amount refunded (can be less than the amount attribute on the charge if a partial refund \ + was issued).', max_digits=7, default=0, decimal_places=2), preserve_default=False, ), migrations.AlterField( model_name='charge', name='customer', - field=models.ForeignKey(related_name='charges', to='djstripe.Customer', help_text='The customer associated with this charge.'), + field=models.ForeignKey(related_name='charges', to='djstripe.Customer', + help_text='The customer associated with this charge.'), ), migrations.AlterField( model_name='charge', @@ -441,7 +538,8 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='charge', name='disputed', - field=djstripe.fields.StripeBooleanField(help_text='Whether or not this charge is disputed.', default=False), + field=djstripe.fields.StripeBooleanField(help_text='Whether or not this charge is disputed.', + default=False), ), migrations.AlterField( model_name='charge', @@ -451,12 +549,16 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='charge', name='paid', - field=djstripe.fields.StripeBooleanField(help_text='True if the charge succeeded, or was successfully authorized for later capture, False otherwise.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='True if the charge succeeded, or was successfully authorized for later capture, \ + False otherwise.', default=False), ), migrations.AlterField( model_name='charge', name='refunded', - field=djstripe.fields.StripeBooleanField(help_text='Whether or not the charge has been fully refunded. If the charge is only partially refunded, this attribute will still be false.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='Whether or not the charge has been fully refunded. If the charge is only partially \ + refunded, this attribute will still be false.', default=False), ), migrations.AlterField( model_name='charge', @@ -466,6 +568,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='charge', name='stripe_timestamp', - field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', null=True), + field=djstripe.fields.StripeDateTimeField(help_text='The datetime this object was created in stripe.', + null=True), ), ] diff --git a/djstripe/migrations/0011_charge_captured_update.py b/djstripe/migrations/0011_charge_captured_update.py index 1836a45d5a..8d609fcc96 100644 --- a/djstripe/migrations/0011_charge_captured_update.py +++ b/djstripe/migrations/0011_charge_captured_update.py @@ -12,6 +12,8 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='charge', name='captured', - field=djstripe.fields.StripeBooleanField(help_text='If the charge was created without capturing, this boolean represents whether or not it is still uncaptured or has since been captured.', default=False), + field=djstripe.fields.StripeBooleanField( + help_text='If the charge was created without capturing, this boolean represents whether or not it is \ + still uncaptured or has since been captured.', default=False), ), ] diff --git a/djstripe/migrations/0012_model_sync.py b/djstripe/migrations/0012_model_sync.py index d5364bf68e..1a8f97a0ee 100644 --- a/djstripe/migrations/0012_model_sync.py +++ b/djstripe/migrations/0012_model_sync.py @@ -29,7 +29,8 @@ def resync_subscriptions(apps, schema_editor): stripe.api_version = "2016-03-07" if Subscription.objects.count(): - print("Purging subscriptions. Don't worry, all active subscriptions will be re-synced from stripe. Just in case you didn't get the memo, we'll print out a json representation of each object for your records:") + print("Purging subscriptions. Don't worry, all active subscriptions will be re-synced from stripe. Just in \ + case you didn't get the memo, we'll print out a json representation of each object for your records:") print(serializers.serialize("json", Subscription.objects.all())) Subscription.objects.all().delete() @@ -39,7 +40,9 @@ def resync_subscriptions(apps, schema_editor): try: Subscription.sync_from_stripe_data(stripe_subscription) except CustomerDoesNotExistLocallyException: - tqdm.write("The customer for this subscription ({subscription_id}) does not exist locally (so we won't sync the subscription). You'll want to figure out how that happened.".format(subscription_id=stripe_subscription['id'])) + tqdm.write("The customer for this subscription ({subscription_id}) does not exist locally (so we \ + won't sync the subscription). You'll want to figure out how that \ + happened.".format(subscription_id=stripe_subscription['id'])) print("Subscription re-sync complete.") @@ -47,9 +50,10 @@ def resync_subscriptions(apps, schema_editor): def resync_invoiceitems(apps, schema_editor): """ Since invoiceitem IDs were not previously stored (the ``stripe_id`` field held the id of the linked subsription), - a direct migration will leave us with a bunch of orphaned objects. It was decided [here](https://github.com/kavdev/dj-stripe/issues/162) - that a purge and re-sync would be the best option for subscriptions. That's being extended to InvoiceItems. - No data that is currently available on stripe will be deleted. Anything stored locally will be purged. + a direct migration will leave us with a bunch of orphaned objects. It was decided + [here](https://github.com/kavdev/dj-stripe/issues/162) that a purge and re-sync would be the best option for + subscriptions. That's being extended to InvoiceItems. No data that is currently available on stripe will be + deleted. Anything stored locally will be purged. """ # This is okay, since we're only doing a forward migration. @@ -59,7 +63,8 @@ def resync_invoiceitems(apps, schema_editor): stripe.api_version = "2016-03-07" if InvoiceItem.objects.count(): - print("Purging invoiceitems. Don't worry, all invoiceitems will be re-synced from stripe. Just in case you didn't get the memo, we'll print out a json representation of each object for your records:") + print("Purging invoiceitems. Don't worry, all invoiceitems will be re-synced from stripe. Just in case you \ + didn't get the memo, we'll print out a json representation of each object for your records:") print(serializers.serialize("json", InvoiceItem.objects.all())) InvoiceItem.objects.all().delete() @@ -69,7 +74,9 @@ def resync_invoiceitems(apps, schema_editor): try: InvoiceItem.sync_from_stripe_data(stripe_invoiceitem) except CustomerDoesNotExistLocallyException: - tqdm.write("The customer for this invoiceitem ({invoiceitem_id}) does not exist locally (so we won't sync the invoiceitem). You'll want to figure out how that happened.".format(invoiceitem_id=stripe_invoiceitem['id'])) + tqdm.write("The customer for this invoiceitem ({invoiceitem_id}) does not exist \ + locally (so we won't sync the invoiceitem). You'll want to figure out how that \ + happened.".format(invoiceitem_id=stripe_invoiceitem['id'])) print("InvoiceItem re-sync complete.") @@ -107,7 +114,8 @@ def sync_invoices(apps, schema_editor): try: Invoice.sync_from_stripe_data(invoice.api_retrieve()) except InvalidRequestError: - tqdm.write("There was an error while syncing invoice ({invoice_id}).".format(invoice_id=invoice.stripe_id)) + tqdm.write("There was an error while syncing invoice \ + ({invoice_id}).".format(invoice_id=invoice.stripe_id)) print("Invoice sync complete.") @@ -126,7 +134,8 @@ def sync_transfers(apps, schema_editor): try: Transfer.sync_from_stripe_data(transfer) except InvalidRequestError: - tqdm.write("There was an error while syncing transfer ({transfer_id}).".format(transfer_id=transfer.stripe_id)) + tqdm.write("There was an error while syncing transfer \ + ({transfer_id}).".format(transfer_id=transfer.stripe_id)) print("Transfer sync complete.") @@ -164,7 +173,8 @@ def sync_customers(apps, schema_editor): try: Customer.sync_from_stripe_data(customer.api_retrieve()) except InvalidRequestError: - tqdm.write("There was an error while syncing customer ({customer_id}).".format(customer_id=customer.stripe_id)) + tqdm.write("There was an error while syncing customer \ + ({customer_id}).".format(customer_id=customer.stripe_id)) except IntegrityError: print(customer.api_retrieve()) six.reraise(*sys.exc_info()) diff --git a/djstripe/migrations/0014_auto_20160625_1851.py b/djstripe/migrations/0014_auto_20160625_1851.py index db950f7a18..05be3d17a5 100644 --- a/djstripe/migrations/0014_auto_20160625_1851.py +++ b/djstripe/migrations/0014_auto_20160625_1851.py @@ -23,11 +23,19 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='charge', name='source', - field=models.ForeignKey(help_text='The source used for this charge.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='charges', to='djstripe.StripeSource'), + field=models.ForeignKey(help_text='The source used for this charge.', null=True, + on_delete=django.db.models.deletion.CASCADE, related_name='charges', + to='djstripe.StripeSource'), ), migrations.AlterField( model_name='subscription', name='application_fee_percent', - field=djstripe.fields.StripePercentField(decimal_places=2, help_text=b'A positive decimal that represents the fee percentage of the subscription invoice amount that will be transferred to the application owner\xe2\x80\x99s Stripe account each billing period.', max_digits=5, null=True, validators=[django.core.validators.MinValueValidator(1.0), django.core.validators.MaxValueValidator(100.0)]), + field=djstripe.fields.StripePercentField( + decimal_places=2, + help_text='A positive decimal that represents the fee percentage of the subscription invoice amount \ + that will be transferred to the application owner\xe2\x80\x99s Stripe account each billing period.', + max_digits=5, null=True, + validators=[django.core.validators.MinValueValidator(1.0), + django.core.validators.MaxValueValidator(100.0)]), ), ] diff --git a/djstripe/migrations/0015_upcoming_invoices.py b/djstripe/migrations/0015_upcoming_invoices.py index 78727fbaca..178fa300c2 100644 --- a/djstripe/migrations/0015_upcoming_invoices.py +++ b/djstripe/migrations/0015_upcoming_invoices.py @@ -2,7 +2,6 @@ # Generated by Django 1.9.1 on 2016-06-25 17:51 from __future__ import unicode_literals -import django.core.validators from django.db import migrations, models import django.db.models.deletion @@ -17,7 +16,10 @@ class Migration(migrations.Migration): migrations.CreateModel( name='UpcomingInvoice', fields=[ - ('invoice_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='djstripe.Invoice')), + ('invoice_ptr', models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, + serialize=False, to='djstripe.Invoice')), ], options={ 'abstract': False, @@ -27,6 +29,8 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='invoiceitem', name='invoice', - field=models.ForeignKey(help_text='The invoice to which this invoiceitem is attached.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='invoiceitems', to='djstripe.Invoice'), + field=models.ForeignKey(help_text='The invoice to which this invoiceitem is attached.', + null=True, on_delete=django.db.models.deletion.CASCADE, + related_name='invoiceitems', to='djstripe.Invoice'), ), ] diff --git a/djstripe/migrations/0016_stripe_id_255_length.py b/djstripe/migrations/0016_stripe_id_255_length.py index 18e32b6da8..40bf44eab1 100644 --- a/djstripe/migrations/0016_stripe_id_255_length.py +++ b/djstripe/migrations/0016_stripe_id_255_length.py @@ -21,7 +21,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='charge', name='source_stripe_id', - field=djstripe.fields.StripeIdField(help_text=b'The payment source id.', max_length=255, null=True), + field=djstripe.fields.StripeIdField(help_text='The payment source id.', max_length=255, null=True), ), migrations.AlterField( model_name='charge', @@ -66,17 +66,22 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='transfer', name='destination', - field=djstripe.fields.StripeIdField(help_text=b'ID of the bank account, card, or Stripe account the transfer was sent to.', max_length=255), + field=djstripe.fields.StripeIdField(help_text='ID of the bank account, card, or Stripe account the \ + transfer was sent to.', max_length=255), ), migrations.AlterField( model_name='transfer', name='destination_payment', - field=djstripe.fields.StripeIdField(help_text=b'If the destination is a Stripe account, this will be the ID of the payment that the destination account received for the transfer.', max_length=255, null=True), + field=djstripe.fields.StripeIdField(help_text='If the destination is a Stripe account, this will be the \ + ID of the payment that the destination account received for the transfer.', max_length=255, null=True), ), migrations.AlterField( model_name='transfer', name='source_transaction', - field=djstripe.fields.StripeIdField(help_text=b'ID of the charge (or other transaction) that was used to fund the transfer. If null, the transfer was funded from the available balance.', max_length=255, null=True), + field=djstripe.fields.StripeIdField( + help_text='ID of the charge (or other transaction) that was used to \ + fund the transfer. If null, the transfer was funded from the available balance.', + max_length=255, null=True), ), migrations.AlterField( model_name='transfer', diff --git a/djstripe/migrations/0017_set_null_on_delete.py b/djstripe/migrations/0017_set_null_on_delete.py index 440c85dd42..3bf448d2d5 100644 --- a/djstripe/migrations/0017_set_null_on_delete.py +++ b/djstripe/migrations/0017_set_null_on_delete.py @@ -16,26 +16,37 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='customer', name='default_source', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='customers', to='djstripe.StripeSource'), + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='customers', + to='djstripe.StripeSource'), ), migrations.AlterField( model_name='charge', name='source', - field=models.ForeignKey(help_text='The source used for this charge.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='charges', to='djstripe.StripeSource'), + field=models.ForeignKey(help_text='The source used for this charge.', null=True, + on_delete=django.db.models.deletion.SET_NULL, related_name='charges', + to='djstripe.StripeSource'), ), migrations.AlterField( model_name='invoice', name='subscription', - field=models.ForeignKey(help_text='The subscription that this invoice was prepared for, if any.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoices', to='djstripe.Subscription'), + field=models.ForeignKey(help_text='The subscription that this invoice was prepared for, if any.', + null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='invoices', to='djstripe.Subscription'), ), migrations.AlterField( model_name='invoiceitem', name='plan', - field=models.ForeignKey(help_text='If the invoice item is a proration, the plan of the subscription for which the proration was computed.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoiceitems', to='djstripe.Plan'), + field=models.ForeignKey( + help_text='If the invoice item is a proration, the plan of the subscription for \ + which the proration was computed.', null=True, on_delete=django.db.models.deletion.SET_NULL, + related_name='invoiceitems', to='djstripe.Plan'), ), migrations.AlterField( model_name='invoiceitem', name='subscription', - field=models.ForeignKey(help_text='The subscription that this invoice item has been created for, if any.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoiceitems', to='djstripe.Subscription'), + field=models.ForeignKey( + help_text='The subscription that this invoice item has been created for, \ + if any.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoiceitems', + to='djstripe.Subscription'), ), ] diff --git a/djstripe/models.py b/djstripe/models.py index 849b4a65a3..d7c920b38c 100644 --- a/djstripe/models.py +++ b/djstripe/models.py @@ -18,7 +18,9 @@ from django.contrib.sites.models import Site from django.core.exceptions import ValidationError from django.core.mail import EmailMessage -from django.db import models +from django.db.models.fields.related import ForeignKey, OneToOneField +from django.db.models.deletion import SET_NULL +from django.db.models.fields import BooleanField, DateTimeField, NullBooleanField, TextField, CharField from django.template.loader import render_to_string from django.utils import six, timezone from django.utils.encoding import python_2_unicode_compatible, smart_text @@ -52,15 +54,33 @@ class Charge(StripeCharge): __doc__ = getattr(StripeCharge, "__doc__") - account = models.ForeignKey("Account", null=True, related_name="charges", help_text="The account the charge was made on behalf of. Null here indicates that this value was never set.") - - customer = models.ForeignKey("Customer", related_name="charges", help_text="The customer associated with this charge.") - transfer = models.ForeignKey("Transfer", null=True, help_text="The transfer to the destination account (only applicable if the charge was created using the destination parameter).") - - source = models.ForeignKey(StripeSource, null=True, related_name="charges", on_delete=models.SET_NULL, - help_text="The source used for this charge.") - - receipt_sent = models.BooleanField(default=False, help_text="Whether or not a receipt was sent for this charge.") + account = ForeignKey( + "Account", null=True, + related_name="charges", + help_text="The account the charge was made on behalf of. Null here indicates that this value was never set." + ) + + customer = ForeignKey( + "Customer", + related_name="charges", + help_text="The customer associated with this charge." + ) + transfer = ForeignKey( + "Transfer", + null=True, + help_text="The transfer to the destination account (only applicable if the charge was created using the " + "destination parameter)." + ) + + source = ForeignKey( + StripeSource, + null=True, + related_name="charges", + on_delete=SET_NULL, + help_text="The source used for this charge." + ) + + receipt_sent = BooleanField(default=False, help_text="Whether or not a receipt was sent for this charge.") objects = ChargeManager() @@ -127,15 +147,16 @@ class Customer(StripeCustomer): """ __doc__ = getattr(StripeCustomer, "__doc__") + doc - # account = models.ForeignKey(Account, related_name="customers") + # account = ForeignKey(Account, related_name="customers") - default_source = models.ForeignKey(StripeSource, null=True, related_name="customers", on_delete=models.SET_NULL) + default_source = ForeignKey(StripeSource, null=True, related_name="customers", on_delete=SET_NULL) - subscriber = models.OneToOneField(getattr(settings, 'DJSTRIPE_SUBSCRIBER_MODEL', settings.AUTH_USER_MODEL), null=True) - date_purged = models.DateTimeField(null=True, editable=False) + subscriber = OneToOneField(getattr(settings, 'DJSTRIPE_SUBSCRIBER_MODEL', settings.AUTH_USER_MODEL), null=True) + date_purged = DateTimeField(null=True, editable=False) def str_parts(self): - return [smart_text(self.subscriber), "email={email}".format(email=self.subscriber.email)] + super(Customer, self).str_parts() + return ([smart_text(self.subscriber), "email={email}".format(email=self.subscriber.email)] + + super(Customer, self).str_parts()) @classmethod def get_or_create(cls, subscriber): @@ -161,7 +182,10 @@ def create(cls, subscriber): customer = Customer.objects.create(subscriber=subscriber, stripe_id=stripe_customer["id"], currency="usd") if djstripe_settings.DEFAULT_PLAN and trial_days: - customer.subscribe(plan=djstripe_settings.DEFAULT_PLAN, trial_end=timezone.now() + timezone.timedelta(days=trial_days)) + customer.subscribe( + plan=djstripe_settings.DEFAULT_PLAN, + trial_end=timezone.now() + timezone.timedelta(days=trial_days) + ) return customer @@ -188,10 +212,12 @@ def purge(self): self.date_purged = timezone.now() self.save() - # TODO: Override Queryset.delete() with a custom manager, since this doesn't get called in bulk deletes (or cascades, but that's another matter) + # TODO: Override Queryset.delete() with a custom manager, since this doesn't get called in bulk deletes + # (or cascades, but that's another matter) def delete(self, using=None, keep_parents=False): """ - Overriding the delete method to keep the customer in the records. All identifying information is removed via the purge() method. + Overriding the delete method to keep the customer in the records. All identifying information is removed + via the purge() method. The only way to delete a customer is to use SQL. @@ -210,8 +236,8 @@ def has_active_subscription(self, plan=None): :param plan: The plan for which to check for an active subscription. If plan is None and there exists only one active subscription, this method will check if that subscription - is valid. Calling this method with no plan and multiple valid subscriptions for this customer will throw - an exception. + is valid. Calling this method with no plan and multiple valid subscriptions for this customer will + throw an exception. :type plan: Plan or string (plan ID) :returns: True if there exists an active subscription, False otherwise. @@ -263,7 +289,8 @@ def subscription(self): elif subscription_count == 1: return self.subscriptions.first() else: - raise MultipleSubscriptionException("This customer has multiple subscriptions. Use Customer.subscriptions to access them.") + raise MultipleSubscriptionException("This customer has multiple subscriptions. Use Customer.subscriptions " + "to access them.") # TODO: Accept a coupon object when coupons are implemented def subscribe(self, plan, charge_immediately=True, **kwargs): @@ -351,7 +378,7 @@ def add_card(self, source, set_default=True): def upcoming_invoice(self, **kwargs): """ Gets the upcoming preview invoice (singular) for this customer. - See `Invoice.upcoming() <#djstripe.models.Invoice.upcoming>`__. + See `Invoice.upcoming() <#djstripe.Invoice.upcoming>`__. The ``customer`` argument to the ``upcoming()`` call is automatically set by this method. """ @@ -382,20 +409,25 @@ def _sync_subscriptions(self, **kwargs): class Event(StripeEvent): __doc__ = getattr(StripeEvent, "__doc__") - # account = models.ForeignKey(Account, related_name="events") - - customer = models.ForeignKey("Customer", null=True, - help_text="In the event that there is a related customer, this will point to that " - "Customer record") - valid = models.NullBooleanField(null=True, - help_text="Tri-state bool. Null == validity not yet confirmed. Otherwise, this " - "field indicates that this event was checked via stripe api and found " - "to be either authentic (valid=True) or in-authentic (possibly " - "malicious)") - - processed = models.BooleanField(default=False, help_text="If validity is performed, webhook event processor(s) " - "may run to take further action on the event. Once these " - "have run, this is set to True.") + # account = ForeignKey(Account, related_name="events") + + customer = ForeignKey( + "Customer", + null=True, + help_text="In the event that there is a related customer, this will point to that Customer record" + ) + valid = NullBooleanField( + null=True, + help_text="Tri-state bool. Null == validity not yet confirmed. Otherwise, this field indicates that this " + "event was checked via stripe api and found to be either authentic (valid=True) or in-authentic (possibly " + "malicious)" + ) + + processed = BooleanField( + default=False, + help_text="If validity is performed, webhook event processor(s) may run to take further action on the event. " + "Once these have run, this is set to True." + ) @property def message(self): @@ -500,7 +532,7 @@ def event_subtype(self): class Transfer(StripeTransfer): __doc__ = getattr(StripeTransfer, "__doc__") - # account = models.ForeignKey("Account", related_name="transfers") + # account = ForeignKey("Account", related_name="transfers") objects = TransferManager() @@ -521,7 +553,7 @@ class Account(StripeAccount): class Card(StripeCard): __doc__ = getattr(StripeCard, "__doc__") - # account = models.ForeignKey("Account", null=True, related_name="cards") + # account = ForeignKey("Account", null=True, related_name="cards") def _attach_objects_hook(self, cls, data): customer = cls._stripe_object_to_customer(target_cls=Customer, data=data) @@ -556,11 +588,25 @@ def remove(self): class Invoice(StripeInvoice): __doc__ = getattr(StripeInvoice, "__doc__") - # account = models.ForeignKey("Account", related_name="invoices") - customer = models.ForeignKey(Customer, related_name="invoices", help_text="The customer associated with this invoice.") - charge = models.OneToOneField(Charge, null=True, related_name="invoice", help_text="The latest charge generated for this invoice, if any.") - subscription = models.ForeignKey("Subscription", null=True, related_name="invoices", on_delete=models.SET_NULL, - help_text="The subscription that this invoice was prepared for, if any.") + # account = ForeignKey("Account", related_name="invoices") + customer = ForeignKey( + Customer, + related_name="invoices", + help_text="The customer associated with this invoice." + ) + charge = OneToOneField( + Charge, + null=True, + related_name="invoice", + help_text="The latest charge generated for this invoice, if any." + ) + subscription = ForeignKey( + "Subscription", + null=True, + related_name="invoices", + on_delete=SET_NULL, + help_text="The subscription that this invoice was prepared for, if any." + ) class Meta(object): ordering = ["-date"] @@ -620,7 +666,7 @@ def plan(self): retrieved from the subscription will be the currently active plan. :returns: The associated plan for the invoice. - :rtype: ``djstripe.models.Plan`` + :rtype: ``djstripe.Plan`` """ for invoiceitem in self.invoiceitems.all(): @@ -674,13 +720,33 @@ def save(self, *args, **kwargs): class InvoiceItem(StripeInvoiceItem): __doc__ = getattr(StripeInvoiceItem, "__doc__") - # account = models.ForeignKey(Account, related_name="invoiceitems") - customer = models.ForeignKey(Customer, related_name="invoiceitems", help_text="The customer associated with this invoiceitem.") - invoice = models.ForeignKey(Invoice, null=True, related_name="invoiceitems", help_text="The invoice to which this invoiceitem is attached.") - plan = models.ForeignKey("Plan", null=True, related_name="invoiceitems", on_delete=models.SET_NULL, - help_text="If the invoice item is a proration, the plan of the subscription for which the proration was computed.") - subscription = models.ForeignKey("Subscription", null=True, related_name="invoiceitems", on_delete=models.SET_NULL, - help_text="The subscription that this invoice item has been created for, if any.") + # account = ForeignKey(Account, related_name="invoiceitems") + customer = ForeignKey( + Customer, + related_name="invoiceitems", + help_text="The customer associated with this invoiceitem." + ) + invoice = ForeignKey( + Invoice, + null=True, + related_name="invoiceitems", + help_text="The invoice to which this invoiceitem is attached." + ) + plan = ForeignKey( + "Plan", + null=True, + related_name="invoiceitems", + on_delete=SET_NULL, + help_text="If the invoice item is a proration, the plan of the subscription for which the proration was " + "computed." + ) + subscription = ForeignKey( + "Subscription", + null=True, + related_name="invoiceitems", + on_delete=SET_NULL, + help_text="The subscription that this invoice item has been created for, if any." + ) def _attach_objects_hook(self, cls, data): customer = cls._stripe_object_to_customer(target_cls=Customer, data=data) @@ -706,7 +772,7 @@ def _attach_objects_hook(self, cls, data): class Plan(StripePlan): __doc__ = getattr(StripePlan, "__doc__") - # account = models.ForeignKey("Account", related_name="plans") + # account = ForeignKey("Account", related_name="plans") class Meta(object): ordering = ["amount"] @@ -756,9 +822,17 @@ def update_name(self): class Subscription(StripeSubscription): __doc__ = getattr(StripeSubscription, "__doc__") - # account = models.ForeignKey("Account", related_name="subscriptions") - customer = models.ForeignKey("Customer", related_name="subscriptions", help_text="The customer associated with this subscription.") - plan = models.ForeignKey("Plan", related_name="subscriptions", help_text="The plan associated with this subscription.") + # account = ForeignKey("Account", related_name="subscriptions") + customer = ForeignKey( + "Customer", + related_name="subscriptions", + help_text="The customer associated with this subscription." + ) + plan = ForeignKey( + "Plan", + related_name="subscriptions", + help_text="The plan associated with this subscription." + ) objects = SubscriptionManager() @@ -808,7 +882,8 @@ def extend(self, delta): return Subscription.sync_from_stripe_data(stripe_subscription) def cancel(self, at_period_end=djstripe_settings.CANCELLATION_AT_PERIOD_END): - # If plan has trial days and customer cancels before trial period ends, then end subscription now, i.e. at_period_end=False + # If plan has trial days and customer cancels before trial period ends, then end subscription now, + # i.e. at_period_end=False if self.trial_end and self.trial_end > timezone.now(): at_period_end = False @@ -826,10 +901,10 @@ def _attach_objects_hook(self, cls, data): @python_2_unicode_compatible class EventProcessingException(TimeStampedModel): - event = models.ForeignKey("Event", null=True) - data = models.TextField() - message = models.CharField(max_length=500) - traceback = models.TextField() + event = ForeignKey("Event", null=True) + data = TextField() + message = CharField(max_length=500) + traceback = TextField() @classmethod def log(cls, data, exception, event): @@ -841,8 +916,11 @@ def log(cls, data, exception, event): ) def __str__(self): - return smart_text("<{message}, pk={pk}, Event={event}>".format(message=self.message, pk=self.pk, event=self.event)) - + return smart_text("<{message}, pk={pk}, Event={event}>".format( + message=self.message, + pk=self.pk, + event=self.event + )) # Much like registering signal handlers. We import this module so that its registrations get picked up # the NO QA directive tells flake8 to not complain about the unused import diff --git a/djstripe/settings.py b/djstripe/settings.py index b1f82da886..16115a300b 100644 --- a/djstripe/settings.py +++ b/djstripe/settings.py @@ -85,7 +85,8 @@ def get_callback_function(setting_name, default=None): def _check_subscriber_for_email_address(subscriber_model, message): """Ensure the custom model has an ``email`` field or property.""" - if ("email" not in [field_.name for field_ in subscriber_model._meta.get_fields()]) and not hasattr(subscriber_model, 'email'): + if (("email" not in [field_.name for field_ in subscriber_model._meta.get_fields()]) and + not hasattr(subscriber_model, 'email')): raise ImproperlyConfigured(message) @@ -118,7 +119,8 @@ def get_subscriber_model(): except ValueError: raise ImproperlyConfigured("DJSTRIPE_SUBSCRIBER_MODEL must be of the form 'app_label.model_name'.") except LookupError: - raise ImproperlyConfigured("DJSTRIPE_SUBSCRIBER_MODEL refers to model '{model}' that has not been installed.".format(model=SUBSCRIBER_MODEL)) + raise ImproperlyConfigured("DJSTRIPE_SUBSCRIBER_MODEL refers to model '{model}' " + "that has not been installed.".format(model=SUBSCRIBER_MODEL)) _check_subscriber_for_email_address(subscriber_model, "DJSTRIPE_SUBSCRIBER_MODEL must have an email attribute.") diff --git a/djstripe/stripe_objects.py b/djstripe/stripe_objects.py index f958f55b11..e8b02cc057 100644 --- a/djstripe/stripe_objects.py +++ b/djstripe/stripe_objects.py @@ -36,7 +36,8 @@ from .context_managers import stripe_temporary_api_version from .exceptions import StripeObjectManipulationException from .fields import (StripeFieldMixin, StripeCharField, StripeDateTimeField, StripePercentField, StripeCurrencyField, - StripeIntegerField, StripeTextField, StripeIdField, StripeBooleanField, StripeNullBooleanField, StripeJSONField) + StripeIntegerField, StripeTextField, StripeIdField, StripeBooleanField, StripeNullBooleanField, + StripeJSONField) from .managers import StripeObjectManager @@ -59,13 +60,25 @@ class StripeObject(TimeStampedModel): stripe_objects = StripeObjectManager() stripe_id = StripeIdField(unique=True, stripe_name='id') - livemode = StripeNullBooleanField(default=False, null=True, stripe_required=False, - help_text="Null here indicates that the livemode status is unknown " - "or was previously unrecorded. Otherwise, this field indicates " - "whether this record comes from Stripe test mode or live " - "mode operation.") - stripe_timestamp = StripeDateTimeField(null=True, stripe_required=False, stripe_name="created", help_text="The datetime this object was created in stripe.") - metadata = StripeJSONField(blank=True, stripe_required=False, help_text="A set of key/value pairs that you can attach to an object. It can be useful for storing additional information about an object in a structured format.") + livemode = StripeNullBooleanField( + default=False, + null=True, + stripe_required=False, + help_text="Null here indicates that the livemode status is unknown or was previously unrecorded. Otherwise, " + "this field indicates whether this record comes from Stripe test mode or live mode operation." + ) + stripe_timestamp = StripeDateTimeField( + null=True, + stripe_required=False, + stripe_name="created", + help_text="The datetime this object was created in stripe." + ) + metadata = StripeJSONField( + blank=True, + stripe_required=False, + help_text="A set of key/value pairs that you can attach to an object. It can be useful for storing additional " + "information about an object in a structured format." + ) description = StripeTextField(blank=True, stripe_required=False, help_text="A description of this object.") class Meta: @@ -260,7 +273,8 @@ def _stripe_object_to_customer(cls, target_cls, data): try: return target_cls.stripe_objects.get_by_json(data, "customer") except target_cls.DoesNotExist: - raise CustomerDoesNotExistLocallyException("Because customers are tied to local users, djstripe will not create customers that do not already exist locally.") + raise CustomerDoesNotExistLocallyException("Because customers are tied to local users, djstripe will " + "not create customers that do not already exist locally.") @classmethod def _stripe_object_to_transfer(cls, target_cls, data): @@ -446,15 +460,46 @@ class Meta: expand_fields = ["balance_transaction"] amount = StripeCurrencyField(help_text="Amount charged.") - amount_refunded = StripeCurrencyField(help_text="Amount refunded (can be less than the amount attribute on the charge if a partial refund was issued).") - captured = StripeBooleanField(default=False, help_text="If the charge was created without capturing, this boolean represents whether or not it is still uncaptured or has since been captured.") - currency = StripeCharField(max_length=3, help_text="Three-letter ISO currency code representing the currency in which the charge was made.") - failure_code = StripeCharField(max_length=30, null=True, choices=CARD_ERROR_CODE_CHOICES, help_text="Error code explaining reason for charge failure if available.") - failure_message = StripeTextField(null=True, help_text="Message to user further explaining reason for charge failure if available.") - paid = StripeBooleanField(default=False, help_text="True if the charge succeeded, or was successfully authorized for later capture, False otherwise.") - refunded = StripeBooleanField(default=False, help_text="Whether or not the charge has been fully refunded. If the charge is only partially refunded, this attribute will still be false.") + amount_refunded = StripeCurrencyField( + help_text="Amount refunded (can be less than the amount attribute on the charge " + "if a partial refund was issued)." + ) + captured = StripeBooleanField( + default=False, + help_text="If the charge was created without capturing, this boolean represents whether or not it is still " + "uncaptured or has since been captured." + ) + currency = StripeCharField( + max_length=3, + help_text="Three-letter ISO currency code representing the currency in which the charge was made." + ) + failure_code = StripeCharField( + max_length=30, + null=True, + choices=CARD_ERROR_CODE_CHOICES, + help_text="Error code explaining reason for charge failure if available." + ) + failure_message = StripeTextField( + null=True, + help_text="Message to user further explaining reason for charge failure if available." + ) + paid = StripeBooleanField( + default=False, + help_text="True if the charge succeeded, or was successfully authorized for later capture, False otherwise." + ) + refunded = StripeBooleanField( + default=False, + help_text="Whether or not the charge has been fully refunded. If the charge is only partially refunded, " + "this attribute will still be false." + ) shipping = StripeJSONField(null=True, help_text="Shipping information for the charge") - statement_descriptor = StripeCharField(max_length=22, null=True, help_text="An arbitrary string to be displayed on your customer's credit card statement. The statement description may not include <>\"' characters, and will appear on your customer's statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.") + statement_descriptor = StripeCharField( + max_length=22, null=True, + help_text="An arbitrary string to be displayed on your customer's credit card statement. The statement " + "description may not include <>\"' characters, and will appear on your customer's statement in capital " + "letters. Non-ASCII characters are automatically stripped. While most banks display this information " + "consistently, some may display it incorrectly or not at all." + ) status = StripeCharField(max_length=10, choices=STATUS_CHOICES, help_text="The status of the payment.") # Balance transaction can be null if the charge failed @@ -462,7 +507,13 @@ class Meta: fee_details = StripeJSONField(stripe_required=False, nested_name="balance_transaction") # dj-stripe custom stripe fields. Don't try to send these. - source_type = StripeCharField(max_length=20, null=True, stripe_name="source.object", help_text="The payment source type. If the payment source is supported by dj-stripe, a corresponding model is attached to this Charge via a foreign key matching this field.") + source_type = StripeCharField( + max_length=20, + null=True, + stripe_name="source.object", + help_text="The payment source type. If the payment source is supported by dj-stripe, a corresponding model is " + "attached to this Charge via a foreign key matching this field." + ) source_stripe_id = StripeIdField(null=True, stripe_name="source.id", help_text="The payment source id.") disputed = StripeBooleanField(default=False, help_text="Whether or not this charge is disputed.") fraudulent = StripeBooleanField(default=False, help_text="Whether or not this charge was marked as fraudulent.") @@ -564,10 +615,30 @@ class Meta: stripe_api_name = "Customer" expand_fields = ["default_source"] - account_balance = StripeIntegerField(null=True, help_text="Current balance, if any, being stored on the customer's account. If negative, the customer has credit to apply to the next invoice. If positive, the customer has an amount owed that will be added to the next invoice. The balance does not refer to any unpaid invoices; it solely takes into account amounts that have yet to be successfully applied to any invoice. This balance is only taken into account for recurring charges.") - business_vat_id = StripeCharField(max_length=20, null=True, help_text="The customer's VAT identification number.", stripe_required=False) - currency = StripeCharField(max_length=3, null=True, help_text="The currency the customer can be charged in for recurring billing purposes (subscriptions, invoices, invoice items).") - delinquent = StripeBooleanField(default=False, help_text="Whether or not the latest charge for the customer's latest invoice has failed.") + account_balance = StripeIntegerField( + null=True, + help_text="Current balance, if any, being stored on the customer's account. If negative, the customer has " + "credit to apply to the next invoice. If positive, the customer has an amount owed that will be added to the " + "next invoice. The balance does not refer to any unpaid invoices; it solely takes into account amounts that " + "have yet to be successfully applied to any invoice. This balance is only taken into account for recurring " + "charges." + ) + business_vat_id = StripeCharField( + max_length=20, + null=True, + stripe_required=False, + help_text="The customer's VAT identification number.", + ) + currency = StripeCharField( + max_length=3, + null=True, + help_text="The currency the customer can be charged in for recurring billing purposes (subscriptions, " + "invoices, invoice items)." + ) + delinquent = StripeBooleanField( + default=False, + help_text="Whether or not the latest charge for the customer's latest invoice has failed." + ) shipping = StripeJSONField(null=True, help_text="Shipping information associated with the customer.") @classmethod @@ -630,12 +701,14 @@ def subscribe(self, plan, application_fee_percent=None, coupon=None, quantity=No customer is being subscribed to. The special value ``now`` can be provided to end the customer's trial immediately. :type trial_end: datetime - :param charge_immediately: Whether or not to charge for the subscription upon creation. If False, an invoice will be created at the end of this period. + :param charge_immediately: Whether or not to charge for the subscription upon creation. If False, an + invoice will be created at the end of this period. :type charge_immediately: boolean .. Notes: .. ``charge_immediately`` is only available on ``Customer.subscribe()`` - .. if you're using ``StripeCustomer.subscribe()`` instead of ``Customer.subscribe()``, ``plan`` can only be a string + .. if you're using ``StripeCustomer.subscribe()`` instead of ``Customer.subscribe()``, ``plan`` \ + can only be a string """ stripe_subscription = StripeSubscription._api_create( @@ -665,7 +738,8 @@ def charge(self, amount, currency, application_fee=None, capture=None, descripti :type amount: Decimal. Precision is 2; anything more will be ignored. :param currency: 3-letter ISO code for currency :type currency: string - :param application_fee: A fee that will be applied to the charge and transfered to the platform owner's account. + :param application_fee: A fee that will be applied to the charge and transfered to the platform owner's + account. :type application_fee: Decimal. Precision is 2; anything more will be ignored. :param capture: Whether or not to immediately capture the charge. When false, the charge issues an authorization (or pre-authorization), and will need to be captured later. Uncaptured @@ -680,7 +754,8 @@ def charge(self, amount, currency, application_fee=None, capture=None, descripti :param shipping: Shipping information for the charge. :type shipping: dict :param source: The source to use for this charge. Must be a source attributed to this customer. If None, - the customer's default source is used. Can be either the id of the source or the source object itself. + the customer's default source is used. Can be either the id of the source or the source object + itself. :type source: string, StripeSource :param statement_descriptor: An arbitrary string to be displayed on the customer's credit card statement. :type statement_descriptor: string @@ -747,7 +822,8 @@ def add_invoice_item(self, amount, currency, description=None, discountable=None :type subscription: Subscription or string (subscription ID) .. Notes: - .. if you're using ``StripeCustomer.add_invoice_item()`` instead of ``Customer.add_invoice_item()``, ``invoice`` and ``subscriptions`` can only be strings + .. if you're using ``StripeCustomer.add_invoice_item()`` instead of ``Customer.add_invoice_item()``, \ + ``invoice`` and ``subscriptions`` can only be strings """ if not isinstance(amount, decimal.Decimal): @@ -808,7 +884,8 @@ class StripeEvent(StripeObject): 1) validate the receipt of a webhook event by doing an event get using the API version of the received hook event. 2) retrieve the referenced object (e.g. the Charge, the Customer, etc) using the plugin's supported API version. - 3) process that event using the retrieved object which will, only now, be in a format that you are certain to understand + 3) process that event using the retrieved object which will, only now, be in a format that you are certain to \ + understand # = Mapping the values of this field isn't currently on our roadmap. Please use the stripe dashboard to check the value of this field instead. @@ -827,9 +904,24 @@ class Meta: stripe_api_name = "Event" type = StripeCharField(max_length=250, help_text="Stripe's event description code") - request_id = StripeCharField(max_length=50, null=True, blank=True, stripe_name="request", help_text="Information about the request that triggered this event, for traceability purposes. If empty string then this is an old entry without that data. If Null then this is not an old entry, but a Stripe 'automated' event with no associated request.") - received_api_version = StripeCharField(max_length=15, blank=True, stripe_name="api_version", help_text="the API version at which the event data was rendered. Blank for old entries only, all new entries will have this value") - webhook_message = StripeJSONField(stripe_name="data", help_text="data received at webhook. data should be considered to be garbage until validity check is run and valid flag is set") + request_id = StripeCharField( + max_length=50, + null=True, + blank=True, + stripe_name="request", + help_text="Information about the request that triggered this event, for traceability purposes. If empty " + "string then this is an old entry without that data. If Null then this is not an old entry, but a Stripe " + "'automated' event with no associated request." + ) + received_api_version = StripeCharField( + max_length=15, blank=True, stripe_name="api_version", help_text="the API version at which the event data was " + "rendered. Blank for old entries only, all new entries will have this value" + ) + webhook_message = StripeJSONField( + stripe_name="data", + help_text="data received at webhook. data should be considered to be garbage until validity check is run " + "and valid flag is set" + ) def str_parts(self): return [ @@ -884,7 +976,9 @@ class Meta: STATUS_CHOICES = [(status, status.replace("_", " ").title()) for status in STATUSES] DESTINATION_TYPES = ["card", "bank_account", "stripe_account"] - DESITNATION_TYPE_CHOICES = [(destination_type, destination_type.replace("_", " ").title()) for destination_type in DESTINATION_TYPES] + DESITNATION_TYPE_CHOICES = [ + (destination_type, destination_type.replace("_", " ").title()) for destination_type in DESTINATION_TYPES + ] SOURCE_TYPES = ["card", "bank_account", "bitcoin_reciever", "alipay_account"] SOURCE_TYPE_CHOICES = [(source_type, source_type.replace("_", " ").title()) for source_type in SOURCE_TYPES] @@ -895,19 +989,69 @@ class Meta: FAILURE_CODE_CHOICES = [(failure_code, failure_code.replace("_", " ").title()) for failure_code in FAILURE_CODES] amount = StripeCurrencyField(help_text="The amount transferred") - amount_reversed = StripeCurrencyField(stripe_required=False, help_text="The amount reversed (can be less than the amount attribute on the transfer if a partial reversal was issued).") + amount_reversed = StripeCurrencyField( + stripe_required=False, + help_text="The amount reversed (can be less than the amount attribute on the transfer if a partial " + "reversal was issued)." + ) currency = StripeCharField(max_length=3, help_text="Three-letter ISO currency code.") - date = StripeDateTimeField(help_text="Date the transfer is scheduled to arrive in the bank. This doesn't factor in delays like weekends or bank holidays.") + date = StripeDateTimeField( + help_text="Date the transfer is scheduled to arrive in the bank. This doesn't factor in delays like " + "weekends or bank holidays." + ) destination = StripeIdField(help_text="ID of the bank account, card, or Stripe account the transfer was sent to.") - destination_payment = StripeIdField(stripe_required=False, help_text="If the destination is a Stripe account, this will be the ID of the payment that the destination account received for the transfer.") - destination_type = StripeCharField(stripe_name="type", max_length=14, choices=DESITNATION_TYPE_CHOICES, help_text="The type of the transfer destination.") - failure_code = StripeCharField(null=True, max_length=23, choices=FAILURE_CODE_CHOICES, help_text="Error code explaining reason for transfer failure if available. See https://stripe.com/docs/api/python#transfer_failures.") - failure_message = StripeTextField(null=True, help_text="Message to user further explaining reason for transfer failure if available.") - reversed = StripeBooleanField(default=False, help_text="Whether or not the transfer has been fully reversed. If the transfer is only partially reversed, this attribute will still be false.") - source_transaction = StripeIdField(null=True, help_text="ID of the charge (or other transaction) that was used to fund the transfer. If null, the transfer was funded from the available balance.") - source_type = StripeCharField(max_length=16, choices=SOURCE_TYPE_CHOICES, help_text="The source balance from which this transfer came.") - statement_descriptor = StripeCharField(max_length=22, null=True, help_text="An arbitrary string to be displayed on your customer's credit card statement. The statement description may not include <>\"' characters, and will appear on your customer's statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.") - status = StripeCharField(max_length=10, choices=STATUS_CHOICES, help_text="The current status of the transfer. A transfer will be pending until it is submitted to the bank, at which point it becomes in_transit. It will then change to paid if the transaction goes through. If it does not go through successfully, its status will change to failed or canceled.") + destination_payment = StripeIdField( + stripe_required=False, + help_text="If the destination is a Stripe account, this will be the ID of the payment that the destination " + "account received for the transfer." + ) + destination_type = StripeCharField( + stripe_name="type", + max_length=14, + choices=DESITNATION_TYPE_CHOICES, + help_text="The type of the transfer destination." + ) + failure_code = StripeCharField( + null=True, + max_length=23, + choices=FAILURE_CODE_CHOICES, + help_text="Error code explaining reason for transfer failure if available. " + "See https://stripe.com/docs/api/python#transfer_failures." + ) + failure_message = StripeTextField( + null=True, + help_text="Message to user further explaining reason for transfer failure if available." + ) + reversed = StripeBooleanField( + default=False, + help_text="Whether or not the transfer has been fully reversed. If the transfer is only partially " + "reversed, this attribute will still be false." + ) + source_transaction = StripeIdField( + null=True, + help_text="ID of the charge (or other transaction) that was used to fund the transfer. " + "If null, the transfer was funded from the available balance." + ) + source_type = StripeCharField( + max_length=16, + choices=SOURCE_TYPE_CHOICES, + help_text="The source balance from which this transfer came." + ) + statement_descriptor = StripeCharField( + max_length=22, + null=True, + help_text="An arbitrary string to be displayed on your customer's credit card statement. The statement " + "description may not include <>\"' characters, and will appear on your customer's statement in capital " + "letters. Non-ASCII characters are automatically stripped. While most banks display this information " + "consistently, some may display it incorrectly or not at all." + ) + status = StripeCharField( + max_length=10, + choices=STATUS_CHOICES, + help_text="The current status of the transfer. A transfer will be pending until it is submitted to the bank, " + "at which point it becomes in_transit. It will then change to paid if the transaction goes through. " + "If it does not go through successfully, its status will change to failed or canceled." + ) # Balance transaction can be null if the transfer failed fee = StripeCurrencyField(stripe_required=False, nested_name="balance_transaction") @@ -992,10 +1136,15 @@ class StripeCard(StripeSource): FUNDING_TYPE_CHOICES = [(funding_type, funding_type.title()) for funding_type in FUNDING_TYPES] CARD_CHECK_RESULTS = ["pass", "fail", "unavailable", "unknown"] - CARD_CHECK_RESULT_CHOICES = [(card_check_result, card_check_result.title()) for card_check_result in CARD_CHECK_RESULTS] + CARD_CHECK_RESULT_CHOICES = [ + (card_check_result, card_check_result.title()) for card_check_result in CARD_CHECK_RESULTS + ] TOKENIZATION_METHODS = ["apple_pay", "android_pay"] - TOKENIZATION_METHOD_CHOICES = [(tokenization_method, tokenization_method.replace("_", " ").title()) for tokenization_method in TOKENIZATION_METHODS] + TOKENIZATION_METHOD_CHOICES = [ + (tokenization_method, tokenization_method.replace("_", " ").title()) + for tokenization_method in TOKENIZATION_METHODS + ] class Meta: abstract = True @@ -1005,34 +1154,60 @@ class Meta: address_city = StripeTextField(null=True, help_text="Billing address city.") address_country = StripeTextField(null=True, help_text="Billing address country.") address_line1 = StripeTextField(null=True, help_text="Billing address (Line 1).") - address_line1_check = StripeCharField(null=True, max_length=11, choices=CARD_CHECK_RESULT_CHOICES, help_text="If ``address_line1`` was provided, results of the check.") + address_line1_check = StripeCharField( + null=True, + max_length=11, + choices=CARD_CHECK_RESULT_CHOICES, + help_text="If ``address_line1`` was provided, results of the check." + ) address_line2 = StripeTextField(null=True, help_text="Billing address (Line 2).") address_state = StripeTextField(null=True, help_text="Billing address state.") address_zip = StripeTextField(null=True, help_text="Billing address zip code.") - address_zip_check = StripeCharField(null=True, max_length=11, choices=CARD_CHECK_RESULT_CHOICES, help_text="If ``address_zip`` was provided, results of the check.") + address_zip_check = StripeCharField( + null=True, + max_length=11, + choices=CARD_CHECK_RESULT_CHOICES, + help_text="If ``address_zip`` was provided, results of the check." + ) brand = StripeCharField(max_length=16, choices=BRAND_CHOICES, help_text="Card brand.") country = StripeCharField(max_length=2, help_text="Two-letter ISO code representing the country of the card.") - cvc_check = StripeCharField(null=True, max_length=11, choices=CARD_CHECK_RESULT_CHOICES, help_text="If a CVC was provided, results of the check.") - dynamic_last4 = StripeCharField(null=True, max_length=4, help_text="(For tokenized numbers only.) The last four digits of the device account number.") + cvc_check = StripeCharField( + null=True, + max_length=11, + choices=CARD_CHECK_RESULT_CHOICES, + help_text="If a CVC was provided, results of the check." + ) + dynamic_last4 = StripeCharField( + null=True, + max_length=4, + help_text="(For tokenized numbers only.) The last four digits of the device account number." + ) exp_month = StripeIntegerField(help_text="Card expiration month.") exp_year = StripeIntegerField(help_text="Card expiration year.") fingerprint = StripeTextField(stripe_required=False, help_text="Uniquely identifies this particular card number.") funding = StripeCharField(max_length=7, choices=FUNDING_TYPE_CHOICES, help_text="Card funding type.") last4 = StripeCharField(max_length=4, help_text="Last four digits of Card number.") name = StripeTextField(null=True, help_text="Cardholder name.") - tokenization_method = StripeCharField(null=True, max_length=11, choices=TOKENIZATION_METHOD_CHOICES, help_text="If the card number is tokenized, this is the method that was used.") + tokenization_method = StripeCharField( + null=True, + max_length=11, + choices=TOKENIZATION_METHOD_CHOICES, + help_text="If the card number is tokenized, this is the method that was used." + ) def api_retrieve(self, api_key=settings.STRIPE_SECRET_KEY): # OVERRIDING the parent version of this function # Cards must be manipulated through a customer or account. - # TODO: When managed accounts are supported, this method needs to check if either a customer or account is supplied to determine the correct object to use. + # TODO: When managed accounts are supported, this method needs to check if either a customer or + # account is supplied to determine the correct object to use. return self.customer.api_retrieve(api_key=api_key).sources.retrieve(self.stripe_id, expand=self.expand_fields) @staticmethod def _get_customer_from_kwargs(**kwargs): if "customer" not in kwargs or not isinstance(kwargs["customer"], StripeCustomer): - raise StripeObjectManipulationException("Cards must be manipulated through a Customer. Pass a Customer object into this call.") + raise StripeObjectManipulationException("Cards must be manipulated through a Customer. " + "Pass a Customer object into this call.") customer = kwargs["customer"] del kwargs["customer"] @@ -1043,7 +1218,8 @@ def _get_customer_from_kwargs(**kwargs): def _api_create(cls, api_key=settings.STRIPE_SECRET_KEY, **kwargs): # OVERRIDING the parent version of this function # Cards must be manipulated through a customer or account. - # TODO: When managed accounts are supported, this method needs to check if either a customer or account is supplied to determine the correct object to use. + # TODO: When managed accounts are supported, this method needs to check if either a customer or + # account is supplied to determine the correct object to use. customer, clean_kwargs = cls._get_customer_from_kwargs(**kwargs) @@ -1053,7 +1229,8 @@ def _api_create(cls, api_key=settings.STRIPE_SECRET_KEY, **kwargs): def api_list(cls, api_key=settings.STRIPE_SECRET_KEY, **kwargs): # OVERRIDING the parent version of this function # Cards must be manipulated through a customer or account. - # TODO: When managed accounts are supported, this method needs to check if either a customer or account is supplied to determine the correct object to use. + # TODO: When managed accounts are supported, this method needs to check if either a customer or + # account is supplied to determine the correct object to use. customer, clean_kwargs = cls._get_customer_from_kwargs(**kwargs) @@ -1128,7 +1305,8 @@ class StripeInvoice(StripeObject): will be actually charged). If the amount due for the invoice is less than 50 cents (the minimum for a charge), we add the amount to the customer's running account balance to be added to the next invoice. If this amount is negative, it will act as a credit to offset the next invoice. Note that the customer account balance does not include unpaid -invoices; it only includes balances that need to be taken into account when calculating the amount due for the next invoice. +invoices; it only includes balances that need to be taken into account when calculating the amount due for the next +invoice. (Source: https://stripe.com/docs/api/python#invoices) # = Mapping the values of this field isn't currently on our roadmap. @@ -1150,25 +1328,92 @@ class Meta: stripe_api_name = "Invoice" - amount_due = StripeCurrencyField(help_text="Final amount due at this time for this invoice. If the invoice's total is smaller than the minimum charge amount, for example, or if there is account credit that can be applied to the invoice, the amount_due may be 0. If there is a positive starting_balance for the invoice (the customer owes money), the amount_due will also take that into account. The charge that gets generated for the invoice will be for the amount specified in amount_due.") - application_fee = StripeCurrencyField(null=True, help_text="The fee in cents that will be applied to the invoice and transferred to the application owner's Stripe account when the invoice is paid.") - attempt_count = StripeIntegerField(help_text="Number of payment attempts made for this invoice, from the perspective of the payment retry schedule. Any payment attempt counts as the first attempt, and subsequently only automatic retries increment the attempt count. In other words, manual payment attempts after the first attempt do not affect the retry schedule.") - attempted = StripeBooleanField(default=False, help_text="Whether or not an attempt has been made to pay the invoice. An invoice is not attempted until 1 hour after the ``invoice.created`` webhook, for example, so you might not want to display that invoice as unpaid to your users.") - closed = StripeBooleanField(default=False, help_text="Whether or not the invoice is still trying to collect payment. An invoice is closed if it's either paid or it has been marked closed. A closed invoice will no longer attempt to collect payment.") + amount_due = StripeCurrencyField( + help_text="Final amount due at this time for this invoice. If the invoice's total is smaller than the minimum " + "charge amount, for example, or if there is account credit that can be applied to the invoice, the amount_due " + "may be 0. If there is a positive starting_balance for the invoice (the customer owes money), the amount_due " + "will also take that into account. The charge that gets generated for the invoice will be for the amount " + "specified in amount_due." + ) + application_fee = StripeCurrencyField( + null=True, + help_text="The fee in cents that will be applied to the invoice and transferred to the application owner's " + "Stripe account when the invoice is paid." + ) + attempt_count = StripeIntegerField( + help_text="Number of payment attempts made for this invoice, from the perspective of the payment retry " + "schedule. Any payment attempt counts as the first attempt, and subsequently only automatic retries " + "increment the attempt count. In other words, manual payment attempts after the first attempt do not affect " + "the retry schedule." + ) + attempted = StripeBooleanField( + default=False, + help_text="Whether or not an attempt has been made to pay the invoice. An invoice is not attempted until 1 " + "hour after the ``invoice.created`` webhook, for example, so you might not want to display that invoice as " + "unpaid to your users." + ) + closed = StripeBooleanField( + default=False, + help_text="Whether or not the invoice is still trying to collect payment. An invoice is closed if it's either " + "paid or it has been marked closed. A closed invoice will no longer attempt to collect payment." + ) currency = StripeCharField(max_length=3, help_text="Three-letter ISO currency code.") date = StripeDateTimeField(help_text="The date on the invoice.") - ending_balance = StripeIntegerField(null=True, help_text="Ending customer balance after attempting to pay invoice. If the invoice has not been attempted yet, this will be null.") - forgiven = StripeBooleanField(default=False, help_text="Whether or not the invoice has been forgiven. Forgiving an invoice instructs us to update the subscription status as if the invoice were successfully paid. Once an invoice has been forgiven, it cannot be unforgiven or reopened.") - next_payment_attempt = StripeDateTimeField(null=True, help_text="The time at which payment will next be attempted.") - paid = StripeBooleanField(default=False, help_text="The time at which payment will next be attempted.") - period_end = StripeDateTimeField(help_text="End of the usage period during which invoice items were added to this invoice.") - period_start = StripeDateTimeField(help_text="Start of the usage period during which invoice items were added to this invoice.") - starting_balance = StripeIntegerField(help_text="Starting customer balance before attempting to pay invoice. If the invoice has not been attempted yet, this will be the current customer balance.") - statement_descriptor = StripeCharField(max_length=22, null=True, help_text="An arbitrary string to be displayed on your customer's credit card statement. The statement description may not include <>\"' characters, and will appear on your customer's statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.") - subscription_proration_date = StripeDateTimeField(stripe_required=False, help_text="Only set for upcoming invoices that preview prorations. The time used to calculate prorations.") - subtotal = StripeCurrencyField(help_text="Only set for upcoming invoices that preview prorations. The time used to calculate prorations.") - tax = StripeCurrencyField(null=True, help_text="The amount of tax included in the total, calculated from ``tax_percent`` and the subtotal. If no ``tax_percent`` is defined, this value will be null.") - tax_percent = StripePercentField(null=True, help_text="This percentage of the subtotal has been added to the total amount of the invoice, including invoice line items and discounts. This field is inherited from the subscription's ``tax_percent`` field, but can be changed before the invoice is paid. This field defaults to null.") + ending_balance = StripeIntegerField( + null=True, + help_text="Ending customer balance after attempting to pay invoice. If the invoice has not been attempted " + "yet, this will be null." + ) + forgiven = StripeBooleanField( + default=False, + help_text="Whether or not the invoice has been forgiven. Forgiving an invoice instructs us to update the " + "subscription status as if the invoice were successfully paid. Once an invoice has been forgiven, it cannot " + "be unforgiven or reopened." + ) + next_payment_attempt = StripeDateTimeField( + null=True, + help_text="The time at which payment will next be attempted." + ) + paid = StripeBooleanField( + default=False, + help_text="The time at which payment will next be attempted." + ) + period_end = StripeDateTimeField( + help_text="End of the usage period during which invoice items were added to this invoice." + ) + period_start = StripeDateTimeField( + help_text="Start of the usage period during which invoice items were added to this invoice." + ) + starting_balance = StripeIntegerField( + help_text="Starting customer balance before attempting to pay invoice. If the invoice has not been attempted " + "yet, this will be the current customer balance." + ) + statement_descriptor = StripeCharField( + max_length=22, + null=True, + help_text="An arbitrary string to be displayed on your customer's credit card statement. The statement " + "description may not include <>\"' characters, and will appear on your customer's statement in capital " + "letters. Non-ASCII characters are automatically stripped. While most banks display this information " + "consistently, some may display it incorrectly or not at all." + ) + subscription_proration_date = StripeDateTimeField( + stripe_required=False, + help_text="Only set for upcoming invoices that preview prorations. The time used to calculate prorations." + ) + subtotal = StripeCurrencyField( + help_text="Only set for upcoming invoices that preview prorations. The time used to calculate prorations." + ) + tax = StripeCurrencyField( + null=True, + help_text="The amount of tax included in the total, calculated from ``tax_percent`` and the subtotal. If no " + "``tax_percent`` is defined, this value will be null." + ) + tax_percent = StripePercentField( + null=True, + help_text="This percentage of the subtotal has been added to the total amount of the invoice, including " + "invoice line items and discounts. This field is inherited from the subscription's ``tax_percent`` field, " + "but can be changed before the invoice is paid. This field defaults to null." + ) total = StripeCurrencyField("Total after discount.") def str_parts(self): @@ -1312,11 +1557,28 @@ class Meta: amount = StripeCurrencyField(help_text="Amount invoiced.") currency = StripeCharField(max_length=3, help_text="Three-letter ISO currency code.") date = StripeDateTimeField(help_text="The date on the invoiceitem.") - discountable = StripeBooleanField(default=False, help_text="If True, discounts will apply to this invoice item. Always False for prorations.") - period_end = StripeDateTimeField(stripe_name="period.end", help_text="Might be the date when this invoiceitem's invoice was sent.") - period_start = StripeDateTimeField(stripe_name="period.start", help_text="Might be the date when this invoiceitem was added to the invoice") - proration = StripeBooleanField(default=False, help_text="Whether or not the invoice item was created automatically as a proration adjustment when the customer switched plans.") - quantity = StripeIntegerField(stripe_required=False, help_text="If the invoice item is a proration, the quantity of the subscription for which the proration was computed.") + discountable = StripeBooleanField( + default=False, + help_text="If True, discounts will apply to this invoice item. Always False for prorations." + ) + period_end = StripeDateTimeField( + stripe_name="period.end", + help_text="Might be the date when this invoiceitem's invoice was sent." + ) + period_start = StripeDateTimeField( + stripe_name="period.start", + help_text="Might be the date when this invoiceitem was added to the invoice" + ) + proration = StripeBooleanField( + default=False, + help_text="Whether or not the invoice item was created automatically as a proration adjustment when the " + "customer switched plans." + ) + quantity = StripeIntegerField( + stripe_required=False, + help_text="If the invoice item is a proration, the quantity of the subscription for which the proration " + "was computed." + ) def str_parts(self): return [ @@ -1365,11 +1627,29 @@ class Meta: amount = StripeCurrencyField(help_text="Amount to be charged on the interval specified.") currency = StripeCharField(max_length=3, help_text="Three-letter ISO currency code") - interval = StripeCharField(max_length=5, choices=INTERVAL_TYPE_CHOICES, help_text="The frequency with which a subscription should be billed.") - interval_count = StripeIntegerField(null=True, help_text="The number of intervals (specified in the interval property) between each subscription billing.") + interval = StripeCharField( + max_length=5, + choices=INTERVAL_TYPE_CHOICES, + help_text="The frequency with which a subscription should be billed." + ) + interval_count = StripeIntegerField( + null=True, + help_text="The number of intervals (specified in the interval property) between each subscription billing." + ) name = StripeTextField(help_text="Name of the plan, to be displayed on invoices and in the web interface.") - statement_descriptor = StripeCharField(max_length=22, null=True, help_text="An arbitrary string to be displayed on your customer's credit card statement. The statement description may not include <>\"' characters, and will appear on your customer's statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.") - trial_period_days = StripeIntegerField(null=True, help_text="Number of trial period days granted when subscribing a customer to this plan. Null if the plan has no trial period.") + statement_descriptor = StripeCharField( + max_length=22, + null=True, + help_text="An arbitrary string to be displayed on your customer's credit card statement. The statement " + "description may not include <>\"' characters, and will appear on your customer's statement in capital " + "letters. Non-ASCII characters are automatically stripped. While most banks display this information " + "consistently, some may display it incorrectly or not at all." + ) + trial_period_days = StripeIntegerField( + null=True, + help_text="Number of trial period days granted when subscribing a customer to this plan. " + "Null if the plan has no trial period." + ) def str_parts(self): return [ @@ -1417,18 +1697,50 @@ class Meta: STATUSES = [STATUS_TRIALING, STATUS_ACTIVE, STATUS_PAST_DUE, STATUS_CANCELED, STATUS_UNPAID] STATUS_CHOICES = [(status, status.replace("_", " ").title()) for status in STATUSES] - application_fee_percent = StripePercentField(null=True, help_text="A positive decimal that represents the fee percentage of the subscription invoice amount that will be transferred to the application owner’s Stripe account each billing period.") - cancel_at_period_end = StripeBooleanField(default=False, help_text="If the subscription has been canceled with the ``at_period_end`` flag set to true, ``cancel_at_period_end`` on the subscription will be true. You can use this attribute to determine whether a subscription that has a status of active is scheduled to be canceled at the end of the current period.") - canceled_at = StripeDateTimeField(null=True, help_text="If the subscription has been canceled, the date of that cancellation. If the subscription was canceled with ``cancel_at_period_end``, canceled_at will still reflect the date of the initial cancellation request, not the end of the subscription period when the subscription is automatically moved to a canceled state.") - current_period_end = StripeDateTimeField(help_text="End of the current period for which the subscription has been invoiced. At the end of this period, a new invoice will be created.") - current_period_start = StripeDateTimeField(help_text="Start of the current period for which the subscription has been invoiced.") - ended_at = StripeDateTimeField(null=True, help_text="If the subscription has ended (either because it was canceled or because the customer was switched to a subscription to a new plan), the date the subscription ended.") + application_fee_percent = StripePercentField( + null=True, + help_text="A positive decimal that represents the fee percentage of the subscription invoice amount that " + "will be transferred to the application owner’s Stripe account each billing period." + ) + cancel_at_period_end = StripeBooleanField( + default=False, + help_text="If the subscription has been canceled with the ``at_period_end`` flag set to true, " + "``cancel_at_period_end`` on the subscription will be true. You can use this attribute to determine whether " + "a subscription that has a status of active is scheduled to be canceled at the end of the current period." + ) + canceled_at = StripeDateTimeField( + null=True, + help_text="If the subscription has been canceled, the date of that cancellation. If the subscription was " + "canceled with ``cancel_at_period_end``, canceled_at will still reflect the date of the initial cancellation " + "request, not the end of the subscription period when the subscription is automatically moved to a canceled " + "state." + ) + current_period_end = StripeDateTimeField( + help_text="End of the current period for which the subscription has been invoiced. At the end of this period, " + "a new invoice will be created." + ) + current_period_start = StripeDateTimeField( + help_text="Start of the current period for which the subscription has been invoiced." + ) + ended_at = StripeDateTimeField( + null=True, + help_text="If the subscription has ended (either because it was canceled or because the customer was switched " + "to a subscription to a new plan), the date the subscription ended." + ) quantity = StripeIntegerField(help_text="The quantity applied to this subscription.") start = StripeDateTimeField(help_text="Date the subscription started.") status = StripeCharField(max_length=8, choices=STATUS_CHOICES, help_text="The status of this subscription.") - tax_percent = StripePercentField(null=True, help_text="A positive decimal (with at most two decimal places) between 1 and 100. This represents the percentage of the subscription invoice subtotal that will be calculated and added as tax to the final amount each billing period.") + tax_percent = StripePercentField( + null=True, + help_text="A positive decimal (with at most two decimal places) between 1 and 100. This represents the " + "percentage of the subscription invoice subtotal that will be calculated and added as tax to the final " + "amount each billing period." + ) trial_end = StripeDateTimeField(null=True, help_text="If the subscription has a trial, the end of that trial.") - trial_start = StripeDateTimeField(null=True, help_text="If the subscription has a trial, the beginning of that trial.") + trial_start = StripeDateTimeField( + null=True, + help_text="If the subscription has a trial, the beginning of that trial." + ) def str_parts(self): return [ @@ -1462,18 +1774,21 @@ def update(self, plan=None, application_fee_percent=None, coupon=None, prorate=N :type plan: Plan or string (plan ID) :param prorate: Whether or not to prorate when switching plans. Default is True. :type prorate: boolean - :param proration_date: If set, the proration will be calculated as though the subscription was updated at the given time. - This can be used to apply exactly the same proration that was previewed with upcoming invoice endpoint. - It can also be used to implement custom proration logic, such as prorating by day instead of by second, - by providing the time that you wish to use for proration calculations. + :param proration_date: If set, the proration will be calculated as though the subscription was updated at the + given time. This can be used to apply exactly the same proration that was previewed + with upcoming invoice endpoint. It can also be used to implement custom proration + logic, such as prorating by day instead of by second, by providing the time that you + wish to use for proration calculations. :type proration_date: datetime .. note:: The default value for ``prorate`` is overridden by the DJSTRIPE_PRORATION_POLICY setting. - .. important:: Updating a subscription by changing the plan or quantity creates a new ``Subscription`` in Stripe (and dj-stripe). + .. important:: Updating a subscription by changing the plan or quantity creates a new ``Subscription`` in \ + Stripe (and dj-stripe). .. Notes: - .. if you're using ``StripeSubscription.update()`` instead of ``Subscription.update()``, ``plan`` can only be a string + .. if you're using ``StripeSubscription.update()`` instead of ``Subscription.update()``, ``plan`` can only \ + be a string """ kwargs = deepcopy(locals()) @@ -1512,17 +1827,22 @@ def extend(self, delta): def cancel(self, at_period_end=None): """ - Cancels this subscription. If you set the at_period_end parameter to true, the subscription will remain active until the end of the period, - at which point it will be canceled and not renewed. By default, the subscription is terminated immediately. In either case, the customer will not be - charged again for the subscription. Note, however, that any pending invoice items that you've created will still be charged for at the end of the period - unless manually deleted. If you've set the subscription to cancel at period end, any pending prorations will also be left in place and collected at the - end of the period, but if the subscription is set to cancel immediately, pending prorations will be removed. - - By default, all unpaid invoices for the customer will be closed upon subscription cancellation. We do this in order to prevent unexpected payment retries - once the customer has canceled a subscription. However, you can reopen the invoices manually after subscription cancellation to have us proceed with automatic - retries, or you could even re-attempt payment yourself on all unpaid invoices before allowing the customer to cancel the subscription at all. - - :param at_period_end: A flag that if set to true will delay the cancellation of the subscription until the end of the current period. Default is False. + Cancels this subscription. If you set the at_period_end parameter to true, the subscription will remain active + until the end of the period, at which point it will be canceled and not renewed. By default, the subscription + is terminated immediately. In either case, the customer will not be charged again for the subscription. Note, + however, that any pending invoice items that you've created will still be charged for at the end of the period + unless manually deleted. If you've set the subscription to cancel at period end, any pending prorations will + also be left in place and collected at the end of the period, but if the subscription is set to cancel + immediately, pending prorations will be removed. + + By default, all unpaid invoices for the customer will be closed upon subscription cancellation. We do this in + order to prevent unexpected payment retries once the customer has canceled a subscription. However, you can + reopen the invoices manually after subscription cancellation to have us proceed with automatic retries, or you + could even re-attempt payment yourself on all unpaid invoices before allowing the customer to cancel the + subscription at all. + + :param at_period_end: A flag that if set to true will delay the cancellation of the subscription until the end + of the current period. Default is False. :type at_period_end: boolean .. important:: If a subscription is cancelled during a trial period, the ``at_period_end`` flag will be \ diff --git a/djstripe/utils.py b/djstripe/utils.py index f4d1da5655..4e77c6f51e 100644 --- a/djstripe/utils.py +++ b/djstripe/utils.py @@ -92,7 +92,7 @@ def dict_nested_accessor(d, name): def convert_tstamp(response, field_name=None): """ - Intended for use converting from a Stripe API timestamp resposne into a native date + Intended for use converting from a Stripe API timestamp response into a native date :rtype: datetime """ diff --git a/djstripe/views.py b/djstripe/views.py index 0978ebf11b..4fb3125376 100644 --- a/djstripe/views.py +++ b/djstripe/views.py @@ -118,9 +118,12 @@ def get(self, request, *args, **kwargs): if not Plan.objects.filter(id=plan_id).exists(): return HttpResponseNotFound() - customer, _created = Customer.get_or_create(subscriber=djstripe_settings.subscriber_request_callback(self.request)) + customer, _created = Customer.get_or_create( + subscriber=djstripe_settings.subscriber_request_callback(self.request) + ) - if customer.subscription and str(customer.subscription.plan.id) == plan_id and customer.subscription.is_valid(): + if (customer.subscription and str(customer.subscription.plan.id) == plan_id and + customer.subscription.is_valid()): message = "You already subscribed to this plan" messages.info(request, message, fail_silently=True) return redirect("djstripe:subscribe") @@ -141,7 +144,9 @@ def post(self, request, *args, **kwargs): form = self.get_form(form_class) if form.is_valid(): try: - customer, _created = Customer.get_or_create(subscriber=djstripe_settings.subscriber_request_callback(self.request)) + customer, _created = Customer.get_or_create( + subscriber=djstripe_settings.subscriber_request_callback(self.request) + ) customer.add_card(self.request.POST.get("stripe_token")) customer.subscribe(form.cleaned_data["plan"]) except StripeError as exc: @@ -171,7 +176,9 @@ class ChangePlanView(LoginRequiredMixin, FormValidMessageMixin, SubscriptionMixi def post(self, request, *args, **kwargs): form = PlanForm(request.POST) - customer, _created = Customer.get_or_create(subscriber=djstripe_settings.subscriber_request_callback(self.request)) + customer, _created = Customer.get_or_create( + subscriber=djstripe_settings.subscriber_request_callback(self.request) + ) if not customer.subscription: form.add_error(None, "You must already be subscribed to a plan before you can change it.") @@ -206,7 +213,9 @@ class CancelSubscriptionView(LoginRequiredMixin, SubscriptionMixin, FormView): success_url = reverse_lazy("djstripe:account") def form_valid(self, form): - customer, _created = Customer.get_or_create(subscriber=djstripe_settings.subscriber_request_callback(self.request)) + customer, _created = Customer.get_or_create( + subscriber=djstripe_settings.subscriber_request_callback(self.request) + ) subscription = customer.subscription.cancel() if subscription.status == subscription.STATUS_CANCELED: diff --git a/docs/__init__.py b/docs/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/conf.py b/docs/conf.py index 666df277b2..e06fd348ac 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,19 +12,18 @@ # serve to show the default. import inspect -import sys import os +import sys import django from django.conf import settings -from django.utils.html import strip_tags from django.utils.encoding import force_text +from django.utils.html import strip_tags # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) - cwd = os.getcwd() parent = os.path.dirname(cwd) sys.path.append(parent) @@ -302,7 +301,8 @@ def process_docstring(app, what, name, obj, options, lines): # Grab the field list from the meta class fields = obj._meta.get_fields() - for field in [_field for _field in fields if _field.name not in ["id", "created", "modified", "polymorphic_ctype"]]: + for field in [_field for _field in fields if _field.name not in ["id", "created", "modified", + "polymorphic_ctype"]]: # Skip ManyToOneRel and ManyToManyRel fields which have no 'verbose_name' or 'help_text' if not hasattr(field, 'verbose_name') or (hasattr(field, 'deprecated') and field.deprecated): continue @@ -326,7 +326,8 @@ def process_docstring(app, what, name, obj, options, lines): # Add the field's type to the docstring if isinstance(field, models.ForeignKey): to = field.rel.to - lines.append(u':type %s: %s to :class:`~%s.%s`' % (field.name, type(field).__name__, to.__module__, to.__name__)) + lines.append(u':type %s: %s to :class:`~%s.%s`' % (field.name, type(field).__name__, + to.__module__, to.__name__)) else: lines.append(u':type %s: %s' % (field.name, type(field).__name__)) diff --git a/runtests.py b/runtests.py index 99b8d6c9ee..7b3d264146 100644 --- a/runtests.py +++ b/runtests.py @@ -1,7 +1,7 @@ -from argparse import ArgumentParser import os import sys +from argparse import ArgumentParser from coverage import Coverage import django from django.conf import settings @@ -14,8 +14,16 @@ def main(): parser = ArgumentParser(description='Run the dj-stripe Test Suite.') - parser.add_argument("--skip-utc", action="store_true", help="Skip any tests that require the system timezone to be in UTC.") - parser.add_argument("--no-coverage", action="store_true", help="Disable checking for 100% code coverage (Not advised).") + parser.add_argument( + "--skip-utc", + action="store_true", + help="Skip any tests that require the system timezone to be in UTC." + ) + parser.add_argument( + "--no-coverage", + action="store_true", + help="Disable checking for 100% code coverage (Not advised)." + ) parser.add_argument("--no-pep8", action="store_true", help="Disable checking for pep8 errors (Not advised).") parser.add_argument("tests", nargs='*', default=['.']) args = parser.parse_args() @@ -36,7 +44,7 @@ def run_test_suite(args): settings.configure( DJSTRIPE_TESTS_SKIP_UTC=skip_utc, - TIME_ZONE='America/Los_Angeles', + TIME_ZONE='UTC', DEBUG=True, USE_TZ=True, DATABASES={ @@ -182,7 +190,7 @@ def run_test_suite(args): from django_nose import NoseTestSuiteRunner - test_runner = NoseTestSuiteRunner(verbosity=1) + test_runner = NoseTestSuiteRunner(verbosity=1, keepdb=True, failfast=True) failures = test_runner.run_tests(tests) if failures: @@ -204,7 +212,8 @@ def run_test_suite(args): sys.exit(1) else: # Announce disabled coverage run - sys.stdout.write(colored(text="\nStep 2: Generating coverage results [SKIPPED].", color="yellow", attrs=["bold"])) + sys.stdout.write(colored(text="\nStep 2: Generating coverage results [SKIPPED].", + color="yellow", attrs=["bold"])) if enable_pep8: # Announce flake8 run @@ -217,20 +226,23 @@ def run_test_suite(args): flake_result = call(["flake8", ".", "--count"]) if flake_result != 0: sys.stderr.write("pep8 errors detected.\n") - sys.stderr.write(colored(text="\nYOUR CHANGES HAVE INTRODUCED PEP8 ERRORS!\n\n", color="red", attrs=["bold"])) + sys.stderr.write(colored(text="\nYOUR CHANGES HAVE INTRODUCED PEP8 ERRORS!\n\n", + color="red", attrs=["bold"])) sys.exit(flake_result) - else: - print("None") else: # Announce disabled coverage run - sys.stdout.write(colored(text="\nStep 3: Checking for pep8 errors [SKIPPED].\n", color="yellow", attrs=["bold"])) + sys.stdout.write(colored(text="\nStep 3: Checking for pep8 errors [SKIPPED].\n", + color="yellow", attrs=["bold"])) # Announce success if enable_coverage and enable_pep8: - sys.stdout.write(colored(text="\nTests completed successfully with no errors. Congrats!\n", color="green", attrs=["bold"])) + sys.stdout.write(colored(text="\nTests completed successfully with no errors. Congrats!\n", + color="green", attrs=["bold"])) else: - sys.stdout.write(colored(text="\nTests completed successfully, but some step(s) were skipped!\n", color="green", attrs=["bold"])) - sys.stdout.write(colored(text="Don't push without running the skipped step(s).\n", color="red", attrs=["bold"])) + sys.stdout.write(colored(text="\nTests completed successfully, but some step(s) were skipped!\n", + color="green", attrs=["bold"])) + sys.stdout.write(colored(text="Don't push without running the skipped step(s).\n", + color="red", attrs=["bold"])) if __name__ == "__main__": main() diff --git a/setup.cfg b/setup.cfg index 4ec6625723..7f05798a50 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,7 +2,6 @@ universal = 1 [flake8] -ignore = E501,E128 max-complexity = 10 max-line-length = 119 exclude = .venv diff --git a/tests/__init__.py b/tests/__init__.py index 7c612128ad..ebe2ec74fb 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -546,7 +546,7 @@ def create(self, source, api_key=None): if fake_card["id"] == source: return fake_card - def retrieve(self, id, expand=None): + def retrieve(self, id, expand=None): # noqa for fake_card in self.card_fakes: if fake_card["id"] == id: return fake_card diff --git a/tests/test_card.py b/tests/test_card.py index cc35c28bc8..86c6c6c720 100644 --- a/tests/test_card.py +++ b/tests/test_card.py @@ -43,13 +43,16 @@ def test_str(self): fake_card = deepcopy(FAKE_CARD) card = Card.sync_from_stripe_data(fake_card) - self.assertEqual("".format( - brand=fake_card["brand"], - last4=fake_card["last4"], - exp_month=fake_card["exp_month"], - exp_year=fake_card["exp_year"], - stripe_id=fake_card["id"] - ), str(card)) + self.assertEqual( + "".format( + brand=fake_card["brand"], + last4=fake_card["last4"], + exp_month=fake_card["exp_month"], + exp_year=fake_card["exp_year"], + stripe_id=fake_card["id"] + ), + str(card) + ) @patch("stripe.Token.create") def test_card_create_token(self, token_create_mock): diff --git a/tests/test_charge.py b/tests/test_charge.py index ed4f541dc9..5c239822d2 100644 --- a/tests/test_charge.py +++ b/tests/test_charge.py @@ -90,7 +90,8 @@ def test_sync_from_stripe_data_no_customer(self, default_account_mock): @patch("stripe.Charge.retrieve") @patch("stripe.Transfer.retrieve") @patch("djstripe.models.Account.get_default_account") - def test_sync_from_stripe_data_with_transfer(self, default_account_mock, transfer_retrieve_mock, charge_retrieve_mock): + def test_sync_from_stripe_data_with_transfer(self, default_account_mock, transfer_retrieve_mock, + charge_retrieve_mock): default_account_mock.return_value = self.account fake_transfer = deepcopy(FAKE_TRANSFER) diff --git a/tests/test_contrib/test_rest_framework_permissions.py b/tests/test_contrib/test_rest_framework_permissions.py index 7f225c27e3..e80fe4aab9 100644 --- a/tests/test_contrib/test_rest_framework_permissions.py +++ b/tests/test_contrib/test_rest_framework_permissions.py @@ -17,7 +17,11 @@ class TestUserHasActiveSubscription(TestCase): def setUp(self): self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com") - self.customer = Customer.objects.create(subscriber=self.user, stripe_id=FAKE_CUSTOMER["id"], currency="usd") + self.customer = Customer.objects.create( + subscriber=self.user, + stripe_id=FAKE_CUSTOMER["id"], + currency="usd" + ) def test_no_user_in_request(self): request = RequestFactory().get('djstripe/') diff --git a/tests/test_contrib/test_views.py b/tests/test_contrib/test_views.py index 2b72385fee..eafc3fb721 100644 --- a/tests/test_contrib/test_views.py +++ b/tests/test_contrib/test_views.py @@ -30,7 +30,11 @@ class RestSubscriptionTest(APITestCase): def setUp(self): self.url = reverse("rest_djstripe:subscription") - self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com", password="password") + self.user = get_user_model().objects.create_user( + username="pydanny", + email="pydanny@gmail.com", + password="password" + ) self.assertTrue(self.client.login(username="pydanny", password="password")) @patch("djstripe.models.Customer.subscribe", autospec=True) diff --git a/tests/test_customer.py b/tests/test_customer.py index fad525265f..342ec66bc4 100644 --- a/tests/test_customer.py +++ b/tests/test_customer.py @@ -23,8 +23,7 @@ from djstripe.models import Account, Customer, Charge, Card, Subscription, Invoice, Plan from tests import (FAKE_CARD, FAKE_CHARGE, FAKE_CUSTOMER, FAKE_ACCOUNT, FAKE_INVOICE, FAKE_INVOICE_III, FAKE_INVOICEITEM, FAKE_PLAN, FAKE_SUBSCRIPTION, FAKE_SUBSCRIPTION_II, - StripeList, FAKE_CARD_V, FAKE_CUSTOMER_II, FAKE_UPCOMING_INVOICE, - datetime_to_unix) + StripeList, FAKE_CARD_V, FAKE_CUSTOMER_II, FAKE_UPCOMING_INVOICE, datetime_to_unix) class TestCustomer(TestCase): @@ -238,7 +237,8 @@ def test_charge_converts_dollars_into_cents(self, charge_create_mock, charge_ret @patch("stripe.Charge.retrieve") @patch("stripe.Charge.create") @patch("stripe.Invoice.retrieve") - def test_charge_doesnt_require_invoice(self, invoice_retrieve_mock, charge_create_mock, charge_retrieve_mock, default_account_mock): + def test_charge_doesnt_require_invoice(self, invoice_retrieve_mock, charge_create_mock, charge_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account fake_charge_copy = deepcopy(FAKE_CHARGE) @@ -401,7 +401,10 @@ def test_send_invoice_success(self, invoice_create_mock): return_status = self.customer.send_invoice() self.assertTrue(return_status) - invoice_create_mock.assert_called_once_with(api_key=settings.STRIPE_SECRET_KEY, customer=self.customer.stripe_id) + invoice_create_mock.assert_called_once_with( + api_key=settings.STRIPE_SECRET_KEY, + customer=self.customer.stripe_id + ) @patch("stripe.Invoice.create") def test_send_invoice_failure(self, invoice_create_mock): @@ -410,7 +413,10 @@ def test_send_invoice_failure(self, invoice_create_mock): return_status = self.customer.send_invoice() self.assertFalse(return_status) - invoice_create_mock.assert_called_once_with(api_key=settings.STRIPE_SECRET_KEY, customer=self.customer.stripe_id) + invoice_create_mock.assert_called_once_with( + api_key=settings.STRIPE_SECRET_KEY, + customer=self.customer.stripe_id + ) @patch("djstripe.models.Invoice.sync_from_stripe_data") @patch("stripe.Invoice.list", return_value=StripeList(data=[deepcopy(FAKE_INVOICE), deepcopy(FAKE_INVOICE_III)])) @@ -441,7 +447,8 @@ def test_sync_charges_none(self, customer_retrieve_mock, charge_list_mock, charg self.assertEqual(0, charge_sync_mock.call_count) @patch("djstripe.models.Subscription.sync_from_stripe_data") - @patch("stripe.Subscription.list", return_value=StripeList(data=[deepcopy(FAKE_SUBSCRIPTION), deepcopy(FAKE_SUBSCRIPTION_II)])) + @patch("stripe.Subscription.list", return_value=StripeList(data=[deepcopy(FAKE_SUBSCRIPTION), + deepcopy(FAKE_SUBSCRIPTION_II)])) @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER)) def test_sync_subscriptions(self, customer_retrieve_mock, subscription_list_mock, subscription_sync_mock): self.customer._sync_subscriptions() @@ -457,7 +464,8 @@ def test_sync_subscriptions_none(self, customer_retrieve_mock, subscription_list @patch("djstripe.models.Customer.send_invoice") @patch("stripe.Subscription.create", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER)) - def test_subscribe_not_charge_immediately(self, customer_retrieve_mock, subscription_create_mock, send_invoice_mock): + def test_subscribe_not_charge_immediately(self, customer_retrieve_mock, subscription_create_mock, + send_invoice_mock): plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN)) self.customer.subscribe(plan=plan, charge_immediately=False) @@ -500,14 +508,16 @@ def test_subscription_shortcut_with_multiple_subscriptions(self, customer_retrie @patch("stripe.Subscription.create") @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER)) - def test_has_active_subscription_with_unspecified_plan_with_multiple_subscriptions(self, customer_retrieve_mock, subscription_create_mock): + def test_has_active_subscription_with_unspecified_plan_with_multiple_subscriptions(self, customer_retrieve_mock, + subscription_create_mock): plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN)) subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription_fake["current_period_end"] = datetime_to_unix(timezone.now() + timezone.timedelta(days=7)) subscription_fake_duplicate = deepcopy(FAKE_SUBSCRIPTION) - subscription_fake_duplicate["current_period_end"] = datetime_to_unix(timezone.now() + timezone.timedelta(days=7)) + subscription_fake_duplicate["current_period_end"] = datetime_to_unix(timezone.now() + + timezone.timedelta(days=7)) subscription_fake_duplicate["id"] = "sub_6lsC8pt7IcF8jd" subscription_create_mock.side_effect = [subscription_fake, subscription_fake_duplicate] @@ -552,7 +562,8 @@ def test_has_active_subscription_with_plan_string(self, customer_retrieve_mock, @patch("djstripe.models.Charge.sync_from_stripe_data") @patch("stripe.Charge.retrieve", return_value=FAKE_CHARGE) @patch("stripe.Charge.create", return_value=FAKE_CHARGE) - def test_charge_not_send_receipt(self, charge_create_mock, charge_retrieve_mock, charge_sync_mock, send_receipt_mock): + def test_charge_not_send_receipt(self, charge_create_mock, charge_retrieve_mock, charge_sync_mock, + send_receipt_mock): self.customer.charge(amount=decimal.Decimal("50.00"), send_receipt=False) self.assertFalse(charge_retrieve_mock.called) @@ -563,18 +574,50 @@ def test_charge_not_send_receipt(self, charge_create_mock, charge_retrieve_mock, @patch("djstripe.models.InvoiceItem.sync_from_stripe_data", return_value="pancakes") @patch("stripe.InvoiceItem.create", return_value=deepcopy(FAKE_INVOICEITEM)) def test_add_invoice_item(self, invoiceitem_create_mock, invoiceitem_sync_mock): - invoiceitem = self.customer.add_invoice_item(amount=decimal.Decimal("50.00"), currency="eur", description="test", invoice=77, subscription=25) + invoiceitem = self.customer.add_invoice_item( + amount=decimal.Decimal("50.00"), + currency="eur", + description="test", + invoice=77, + subscription=25, + ) self.assertEqual("pancakes", invoiceitem) - invoiceitem_create_mock.assert_called_once_with(api_key=settings.STRIPE_SECRET_KEY, amount=5000, customer=self.customer.stripe_id, currency="eur", description="test", discountable=None, invoice=77, metadata=None, subscription=25) + invoiceitem_create_mock.assert_called_once_with( + api_key=settings.STRIPE_SECRET_KEY, + amount=5000, + customer=self.customer.stripe_id, + currency="eur", + description="test", + discountable=None, + invoice=77, + metadata=None, + subscription=25, + ) @patch("djstripe.models.InvoiceItem.sync_from_stripe_data", return_value="pancakes") @patch("stripe.InvoiceItem.create", return_value=deepcopy(FAKE_INVOICEITEM)) def test_add_invoice_item_djstripe_objects(self, invoiceitem_create_mock, invoiceitem_sync_mock): - invoiceitem = self.customer.add_invoice_item(amount=decimal.Decimal("50.00"), currency="eur", description="test", invoice=Invoice(stripe_id=77), subscription=Subscription(stripe_id=25)) + invoiceitem = self.customer.add_invoice_item( + amount=decimal.Decimal("50.00"), + currency="eur", + description="test", + invoice=Invoice(stripe_id=77), + subscription=Subscription(stripe_id=25), + ) self.assertEqual("pancakes", invoiceitem) - invoiceitem_create_mock.assert_called_once_with(api_key=settings.STRIPE_SECRET_KEY, amount=5000, customer=self.customer.stripe_id, currency="eur", description="test", discountable=None, invoice=77, metadata=None, subscription=25) + invoiceitem_create_mock.assert_called_once_with( + api_key=settings.STRIPE_SECRET_KEY, + amount=5000, + customer=self.customer.stripe_id, + currency="eur", + description="test", + discountable=None, + invoice=77, + metadata=None, + subscription=25, + ) def test_add_invoice_item_bad_decimal(self): with self.assertRaisesMessage(ValueError, "You must supply a decimal value representing dollars."): diff --git a/tests/test_email.py b/tests/test_email.py index 7a67002fbe..127fbd44f7 100644 --- a/tests/test_email.py +++ b/tests/test_email.py @@ -30,7 +30,8 @@ def setUp(self): @patch("djstripe.models.Account.get_default_account") @patch("stripe.Charge.retrieve") @patch("stripe.Charge.create") - def test_email_reciept_renders_amount_properly(self, charge_create_mock, charge_retrieve_mock, default_account_mock): + def test_email_reciept_renders_amount_properly(self, charge_create_mock, charge_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account fake_charge_copy = deepcopy(FAKE_CHARGE) diff --git a/tests/test_event_handlers.py b/tests/test_event_handlers.py index 580186a2be..d6532c3721 100644 --- a/tests/test_event_handlers.py +++ b/tests/test_event_handlers.py @@ -192,7 +192,8 @@ def test_customer_source_double_delete(self, customer_retrieve_mock): @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER)) @patch("stripe.Event.retrieve") - def test_customer_subscription_created(self, event_retrieve_mock, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock): + def test_customer_subscription_created(self, event_retrieve_mock, customer_retrieve_mock, + subscription_retrieve_mock, plan_retrieve_mock): fake_stripe_event = deepcopy(FAKE_EVENT_CUSTOMER_SUBSCRIPTION_CREATED) event_retrieve_mock.return_value = fake_stripe_event @@ -255,8 +256,9 @@ class TestInvoiceEvents(EventTestCase): @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) @patch("stripe.Invoice.retrieve") @patch("stripe.Event.retrieve") - def test_invoice_created_no_existing_customer(self, event_retrieve_mock, invoice_retrieve_mock, charge_retrieve_mock, - customer_retrieve_mock, subscription_retrieve_mock, default_account_mock, send_receipt_mock): + def test_invoice_created_no_existing_customer(self, event_retrieve_mock, invoice_retrieve_mock, + charge_retrieve_mock, customer_retrieve_mock, + subscription_retrieve_mock, default_account_mock, send_receipt_mock): default_account_mock.return_value = Account.objects.create() user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com") @@ -284,7 +286,8 @@ def test_invoice_created_no_existing_customer(self, event_retrieve_mock, invoice @patch("stripe.Invoice.retrieve") @patch("stripe.Event.retrieve") def test_invoice_created(self, event_retrieve_mock, invoice_retrieve_mock, charge_retrieve_mock, - customer_retrieve_mock, subscription_retrieve_mock, default_account_mock, send_receipt_mock): + customer_retrieve_mock, subscription_retrieve_mock, default_account_mock, + send_receipt_mock): default_account_mock.return_value = Account.objects.create() user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com") @@ -301,7 +304,10 @@ def test_invoice_created(self, event_retrieve_mock, invoice_retrieve_mock, charg event.process() invoice = Invoice.objects.get(stripe_id=fake_stripe_event["data"]["object"]["id"]) - self.assertEquals(invoice.amount_due, fake_stripe_event["data"]["object"]["amount_due"] / decimal.Decimal("100")) + self.assertEquals( + invoice.amount_due, + fake_stripe_event["data"]["object"]["amount_due"] / decimal.Decimal("100") + ) self.assertEquals(invoice.paid, fake_stripe_event["data"]["object"]["paid"]) @patch("djstripe.models.Charge.send_receipt", autospec=True) @@ -339,7 +345,8 @@ class TestInvoiceItemEvents(EventTestCase): @patch("stripe.InvoiceItem.retrieve") @patch("stripe.Event.retrieve") def test_invoiceitem_created(self, event_retrieve_mock, invoiceitem_retrieve_mock, invoice_retrieve_mock, - charge_retrieve_mock, customer_retrieve_mock, subscription_retrieve_mock, default_account_mock): + charge_retrieve_mock, customer_retrieve_mock, subscription_retrieve_mock, + default_account_mock): default_account_mock.return_value = Account.objects.create() user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com") diff --git a/tests/test_event_processing_exception.py b/tests/test_event_processing_exception.py index 3152da7857..ea211a6590 100644 --- a/tests/test_event_processing_exception.py +++ b/tests/test_event_processing_exception.py @@ -76,7 +76,8 @@ def setUp(self): def test_tostring(self): # Not sure if this is normal, but self.exception returns: - # AssertionError: '' != '' + # AssertionError: '' != '' # - # ? -- # + > diff --git a/tests/test_invoice.py b/tests/test_invoice.py index 39a2a33882..f791e0eafd 100644 --- a/tests/test_invoice.py +++ b/tests/test_invoice.py @@ -18,7 +18,8 @@ Subscription, Plan from djstripe.models import InvalidRequestError -from tests import FAKE_INVOICE, FAKE_CHARGE, FAKE_CUSTOMER, FAKE_SUBSCRIPTION, FAKE_PLAN, FAKE_INVOICEITEM_II, FAKE_UPCOMING_INVOICE +from tests import (FAKE_INVOICE, FAKE_CHARGE, FAKE_CUSTOMER, FAKE_SUBSCRIPTION, FAKE_PLAN, FAKE_INVOICEITEM_II, + FAKE_UPCOMING_INVOICE) class InvoiceTest(TestCase): @@ -35,18 +36,22 @@ def test_str(self, charge_retrieve_mock, subscription_retrive_mock, default_acco default_account_mock.return_value = self.account invoice = Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE)) - self.assertEqual(str(invoice), "".format( - amount_due=invoice.amount_due, - date=invoice.date, - status=invoice.status, - stripe_id=invoice.stripe_id - )) + self.assertEqual( + "".format( + amount_due=invoice.amount_due, + date=invoice.date, + status=invoice.status, + stripe_id=invoice.stripe_id + ), + str(invoice) + ) @patch("stripe.Invoice.retrieve") @patch("djstripe.models.Account.get_default_account") @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_retry_true(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock, invoice_retrieve_mock): + def test_retry_true(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock, + invoice_retrieve_mock): default_account_mock.return_value = self.account fake_invoice = deepcopy(FAKE_INVOICE) @@ -64,7 +69,8 @@ def test_retry_true(self, charge_retrieve_mock, subscription_retrieve_mock, defa @patch("djstripe.models.Account.get_default_account") @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_retry_false(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock, invoice_retrieve_mock): + def test_retry_false(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock, + invoice_retrieve_mock): default_account_mock.return_value = self.account fake_invoice = deepcopy(FAKE_INVOICE) @@ -127,7 +133,8 @@ def test_status_closed(self, charge_retrieve_mock, subscription_retrieve_mock, d @patch("djstripe.models.Account.get_default_account") @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_sync_send_emails_false(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock, send_receipt_mock, settings_fake): + def test_sync_send_emails_false(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock, + send_receipt_mock, settings_fake): default_account_mock.return_value = self.account settings_fake.SEND_INVOICE_RECEIPT_EMAILS = False @@ -140,7 +147,8 @@ def test_sync_send_emails_false(self, charge_retrieve_mock, subscription_retriev @patch("stripe.Plan.retrieve", return_value=deepcopy(FAKE_PLAN)) @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_sync_no_subscription(self, charge_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock, default_account_mock): + def test_sync_no_subscription(self, charge_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account invoice_data = deepcopy(FAKE_INVOICE) @@ -157,7 +165,8 @@ def test_sync_no_subscription(self, charge_retrieve_mock, subscription_retrieve_ @patch("djstripe.models.Account.get_default_account") @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_invoice_with_subscription_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock): + def test_invoice_with_subscription_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account invoice_data = deepcopy(FAKE_INVOICE) @@ -165,13 +174,15 @@ def test_invoice_with_subscription_invoice_items(self, charge_retrieve_mock, sub items = invoice.invoiceitems.all() self.assertEquals(1, len(items)) - item_id = "{invoice_id}-{subscription_id}".format(invoice_id=invoice.stripe_id, subscription_id=FAKE_SUBSCRIPTION["id"]) + item_id = "{invoice_id}-{subscription_id}".format(invoice_id=invoice.stripe_id, + subscription_id=FAKE_SUBSCRIPTION["id"]) self.assertEquals(item_id, items[0].stripe_id) @patch("djstripe.models.Account.get_default_account") @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_invoice_with_no_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock): + def test_invoice_with_no_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account invoice_data = deepcopy(FAKE_INVOICE) @@ -184,7 +195,8 @@ def test_invoice_with_no_invoice_items(self, charge_retrieve_mock, subscription_ @patch("djstripe.models.Account.get_default_account") @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_invoice_with_non_subscription_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock): + def test_invoice_with_non_subscription_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account invoice_data = deepcopy(FAKE_INVOICE) @@ -198,7 +210,8 @@ def test_invoice_with_non_subscription_invoice_items(self, charge_retrieve_mock, @patch("djstripe.models.Account.get_default_account") @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_invoice_plan_from_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock): + def test_invoice_plan_from_invoice_items(self, charge_retrieve_mock, subscription_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account invoice_data = deepcopy(FAKE_INVOICE) @@ -210,7 +223,8 @@ def test_invoice_plan_from_invoice_items(self, charge_retrieve_mock, subscriptio @patch("djstripe.models.Account.get_default_account") @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE)) - def test_invoice_plan_from_subscription(self, charge_retrieve_mock, subscription_retrieve_mock, default_account_mock): + def test_invoice_plan_from_subscription(self, charge_retrieve_mock, subscription_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account invoice_data = deepcopy(FAKE_INVOICE) @@ -258,7 +272,8 @@ def test_upcoming_invoice(self, invoice_upcoming_mock, subscription_retrieve_moc @patch("stripe.Plan.retrieve", return_value=deepcopy(FAKE_PLAN)) @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Invoice.upcoming", return_value=deepcopy(FAKE_UPCOMING_INVOICE)) - def test_upcoming_invoice_with_subscription(self, invoice_upcoming_mock, subscription_retrieve_mock, plan_retrieve_mock): + def test_upcoming_invoice_with_subscription(self, invoice_upcoming_mock, subscription_retrieve_mock, + plan_retrieve_mock): invoice = Invoice.upcoming(subscription=Subscription(stripe_id=FAKE_SUBSCRIPTION["id"])) self.assertIsNotNone(invoice) self.assertIsNone(invoice.stripe_id) @@ -273,7 +288,8 @@ def test_upcoming_invoice_with_subscription(self, invoice_upcoming_mock, subscri @patch("stripe.Plan.retrieve", return_value=deepcopy(FAKE_PLAN)) @patch("stripe.Subscription.retrieve", return_value=deepcopy(FAKE_SUBSCRIPTION)) @patch("stripe.Invoice.upcoming", return_value=deepcopy(FAKE_UPCOMING_INVOICE)) - def test_upcoming_invoice_with_subscription_plan(self, invoice_upcoming_mock, subscription_retrieve_mock, plan_retrieve_mock): + def test_upcoming_invoice_with_subscription_plan(self, invoice_upcoming_mock, subscription_retrieve_mock, + plan_retrieve_mock): invoice = Invoice.upcoming(subscription_plan=Plan(stripe_id=FAKE_PLAN["id"])) self.assertIsNotNone(invoice) self.assertIsNone(invoice.stripe_id) diff --git a/tests/test_invoiceitem.py b/tests/test_invoiceitem.py index b048cedc61..24c222dd07 100644 --- a/tests/test_invoiceitem.py +++ b/tests/test_invoiceitem.py @@ -13,7 +13,8 @@ from mock import patch from djstripe.models import Customer, InvoiceItem, Account -from tests import FAKE_INVOICEITEM, FAKE_INVOICE_II, FAKE_CHARGE_II, FAKE_CUSTOMER_II, FAKE_SUBSCRIPTION_III, FAKE_PLAN_II +from tests import (FAKE_INVOICEITEM, FAKE_INVOICE_II, FAKE_CHARGE_II, FAKE_CUSTOMER_II, FAKE_SUBSCRIPTION_III, + FAKE_PLAN_II) class InvoiceItemTest(TestCase): @@ -29,7 +30,8 @@ def setUp(self): @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER_II)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE_II)) @patch("stripe.Invoice.retrieve", return_value=deepcopy(FAKE_INVOICE_II)) - def test_str(self, invoice_retrieve_mock, charge_retrieve_mock, customer_retrieve_mock, subscription_retrieve_mock, default_account_mock): + def test_str(self, invoice_retrieve_mock, charge_retrieve_mock, customer_retrieve_mock, subscription_retrieve_mock, + default_account_mock): default_account_mock.return_value = self.account invoiceitem_data = deepcopy(FAKE_INVOICEITEM) @@ -46,7 +48,8 @@ def test_str(self, invoice_retrieve_mock, charge_retrieve_mock, customer_retriev @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER_II)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE_II)) @patch("stripe.Invoice.retrieve", return_value=deepcopy(FAKE_INVOICE_II)) - def test_sync_with_subscription(self, invoice_retrieve_mock, charge_retrieve_mock, customer_retrieve_mock, subscription_retrieve_mock, default_account_mock): + def test_sync_with_subscription(self, invoice_retrieve_mock, charge_retrieve_mock, customer_retrieve_mock, + subscription_retrieve_mock, default_account_mock): default_account_mock.return_value = self.account invoiceitem_data = deepcopy(FAKE_INVOICEITEM) @@ -61,7 +64,8 @@ def test_sync_with_subscription(self, invoice_retrieve_mock, charge_retrieve_moc @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER_II)) @patch("stripe.Charge.retrieve", return_value=deepcopy(FAKE_CHARGE_II)) @patch("stripe.Invoice.retrieve", return_value=deepcopy(FAKE_INVOICE_II)) - def test_sync_proration(self, invoice_retrieve_mock, charge_retrieve_mock, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock, default_account_mock): + def test_sync_proration(self, invoice_retrieve_mock, charge_retrieve_mock, customer_retrieve_mock, + subscription_retrieve_mock, plan_retrieve_mock, default_account_mock): default_account_mock.return_value = self.account invoiceitem_data = deepcopy(FAKE_INVOICEITEM) diff --git a/tests/test_managers.py b/tests/test_managers.py index a5140b14df..cc9a3fc9c4 100644 --- a/tests/test_managers.py +++ b/tests/test_managers.py @@ -24,14 +24,17 @@ def setUp(self): # create customers and current subscription records period_start = datetime.datetime(2013, 4, 1, tzinfo=timezone.utc) period_end = datetime.datetime(2013, 4, 30, tzinfo=timezone.utc) - start = datetime.datetime(2013, 1, 1, 0, 0, 1) # more realistic start + start = datetime.datetime(2013, 1, 1, 0, 0, 1, tzinfo=timezone.utc) # more realistic start self.plan = Plan.sync_from_stripe_data(FAKE_PLAN) self.plan2 = Plan.sync_from_stripe_data(FAKE_PLAN_II) for i in range(10): customer = Customer.objects.create( - subscriber=get_user_model().objects.create_user(username="patrick{0}".format(i), email="patrick{0}@gmail.com".format(i)), + subscriber=get_user_model().objects.create_user( + username="patrick{0}".format(i), + email="patrick{0}@gmail.com".format(i) + ), stripe_id="cus_xxxxxxxxxxxxxx{0}".format(i), currency="usd", ) @@ -48,7 +51,10 @@ def setUp(self): ) customer = Customer.objects.create( - subscriber=get_user_model().objects.create_user(username="patrick{0}".format(11), email="patrick{0}@gmail.com".format(11)), + subscriber=get_user_model().objects.create_user( + username="patrick{0}".format(11), + email="patrick{0}@gmail.com".format(11) + ), stripe_id="cus_xxxxxxxxxxxxxx{0}".format(11), currency="usd", ) @@ -65,7 +71,10 @@ def setUp(self): ) customer = Customer.objects.create( - subscriber=get_user_model().objects.create_user(username="patrick{0}".format(12), email="patrick{0}@gmail.com".format(12)), + subscriber=get_user_model().objects.create_user( + username="patrick{0}".format(12), + email="patrick{0}@gmail.com".format(12) + ), stripe_id="cus_xxxxxxxxxxxxxx{0}".format(12), currency="usd", ) @@ -147,7 +156,7 @@ def setUp(self): self.march_charge = Charge.objects.create( stripe_id="ch_XXXXMAR1", customer=customer, - stripe_timestamp=datetime.datetime(2015, 3, 31), + stripe_timestamp=datetime.datetime(2015, 3, 31, tzinfo=timezone.utc), amount=0, amount_refunded=0, currency="usd", @@ -159,7 +168,7 @@ def setUp(self): self.april_charge_1 = Charge.objects.create( stripe_id="ch_XXXXAPR1", customer=customer, - stripe_timestamp=datetime.datetime(2015, 4, 1), + stripe_timestamp=datetime.datetime(2015, 4, 1, tzinfo=timezone.utc), amount=decimal.Decimal("20.15"), amount_refunded=0, currency="usd", @@ -172,7 +181,7 @@ def setUp(self): self.april_charge_2 = Charge.objects.create( stripe_id="ch_XXXXAPR2", customer=customer, - stripe_timestamp=datetime.datetime(2015, 4, 18), + stripe_timestamp=datetime.datetime(2015, 4, 18, tzinfo=timezone.utc), amount=decimal.Decimal("10.35"), amount_refunded=decimal.Decimal("5.35"), currency="usd", @@ -185,7 +194,7 @@ def setUp(self): self.april_charge_3 = Charge.objects.create( stripe_id="ch_XXXXAPR3", customer=customer, - stripe_timestamp=datetime.datetime(2015, 4, 30), + stripe_timestamp=datetime.datetime(2015, 4, 30, tzinfo=timezone.utc), amount=decimal.Decimal("100.00"), amount_refunded=decimal.Decimal("80.00"), currency="usd", @@ -198,7 +207,7 @@ def setUp(self): self.may_charge = Charge.objects.create( stripe_id="ch_XXXXMAY1", customer=customer, - stripe_timestamp=datetime.datetime(2015, 5, 1), + stripe_timestamp=datetime.datetime(2015, 5, 1, tzinfo=timezone.utc), amount=0, amount_refunded=0, currency="usd", @@ -210,7 +219,7 @@ def setUp(self): self.november_charge = Charge.objects.create( stripe_id="ch_XXXXNOV1", customer=customer, - stripe_timestamp=datetime.datetime(2015, 11, 16), + stripe_timestamp=datetime.datetime(2015, 11, 16, tzinfo=timezone.utc), amount=0, amount_refunded=0, currency="usd", @@ -222,7 +231,7 @@ def setUp(self): self.charge_2014 = Charge.objects.create( stripe_id="ch_XXXX20141", customer=customer, - stripe_timestamp=datetime.datetime(2014, 12, 31), + stripe_timestamp=datetime.datetime(2014, 12, 31, tzinfo=timezone.utc), amount=0, amount_refunded=0, currency="usd", @@ -234,7 +243,7 @@ def setUp(self): self.charge_2016 = Charge.objects.create( stripe_id="ch_XXXX20161", customer=customer, - stripe_timestamp=datetime.datetime(2016, 1, 1), + stripe_timestamp=datetime.datetime(2016, 1, 1, tzinfo=timezone.utc), amount=0, amount_refunded=0, currency="usd", @@ -262,4 +271,7 @@ def test_get_paid_totals_for_april_2015(self): self.assertEqual(decimal.Decimal("30.50"), paid_totals["total_amount"], "Total amount is not correct.") self.assertEqual(decimal.Decimal("4.90"), paid_totals["total_fee"], "Total fees is not correct.") - self.assertEqual(decimal.Decimal("5.35"), paid_totals["total_refunded"], "Total amount refunded is not correct.") + self.assertEqual( + decimal.Decimal("5.35"), + paid_totals["total_refunded"], "Total amount refunded is not correct." + ) diff --git a/tests/test_plan.py b/tests/test_plan.py index e48f4a4942..b085ddb27a 100644 --- a/tests/test_plan.py +++ b/tests/test_plan.py @@ -82,10 +82,16 @@ def test_create_with_metadata(self, api_create_mock, object_create_mock): object_create_mock.assert_called_once_with(metadata=metadata, stripe_id=1, arg1=1, arg2=2, amount=1) def test_str(self): - self.assertEqual("".format(name=self.plan_data["name"], stripe_id=self.plan_data["id"]), str(self.plan)) + self.assertEqual("".format( + name=self.plan_data["name"], + stripe_id=self.plan_data["id"]), str(self.plan) + ) @patch("stripe.Plan.retrieve", return_value="soup") def test_stripe_plan(self, plan_retrieve_mock): self.assertEqual("soup", self.plan.api_retrieve()) - plan_retrieve_mock.assert_called_once_with(id=self.plan_data["id"], api_key=settings.STRIPE_SECRET_KEY, - expand=None) + plan_retrieve_mock.assert_called_once_with( + id=self.plan_data["id"], + api_key=settings.STRIPE_SECRET_KEY, + expand=None + ) diff --git a/tests/test_settings.py b/tests/test_settings.py index c7b1e1ecdc..d19489fb4e 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -23,35 +23,71 @@ def test_with_user(self): user_model = get_subscriber_model() self.assertTrue(isinstance(user_model, ModelBase)) - @override_settings(DJSTRIPE_SUBSCRIBER_MODEL='testapp.Organization', DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org)) + @override_settings( + DJSTRIPE_SUBSCRIBER_MODEL='testapp.Organization', + DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org) + ) def test_with_org(self): org_model = get_subscriber_model() self.assertTrue(isinstance(org_model, ModelBase)) - @override_settings(DJSTRIPE_SUBSCRIBER_MODEL='testapp.StaticEmailOrganization', DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org)) + @override_settings( + DJSTRIPE_SUBSCRIBER_MODEL='testapp.StaticEmailOrganization', + DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org) + ) def test_with_org_static(self): org_model = get_subscriber_model() self.assertTrue(isinstance(org_model, ModelBase)) - @override_settings(DJSTRIPE_SUBSCRIBER_MODEL='testappStaticEmailOrganization', DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org)) + @override_settings( + DJSTRIPE_SUBSCRIBER_MODEL='testappStaticEmailOrganization', + DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org) + ) def test_bad_model_name(self): - self.assertRaisesMessage(ImproperlyConfigured, "DJSTRIPE_SUBSCRIBER_MODEL must be of the form 'app_label.model_name'.", get_subscriber_model) - - @override_settings(DJSTRIPE_SUBSCRIBER_MODEL='testapp.UnknownModel', DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org)) + self.assertRaisesMessage( + ImproperlyConfigured, + "DJSTRIPE_SUBSCRIBER_MODEL must be of the form 'app_label.model_name'.", + get_subscriber_model + ) + + @override_settings( + DJSTRIPE_SUBSCRIBER_MODEL='testapp.UnknownModel', + DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org) + ) def test_unknown_model(self): - self.assertRaisesMessage(ImproperlyConfigured, "DJSTRIPE_SUBSCRIBER_MODEL refers to model 'testapp.UnknownModel' that has not been installed.", get_subscriber_model) - - @override_settings(DJSTRIPE_SUBSCRIBER_MODEL='testapp.NoEmailOrganization', DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org)) + self.assertRaisesMessage( + ImproperlyConfigured, + "DJSTRIPE_SUBSCRIBER_MODEL refers to model 'testapp.UnknownModel' that has not been installed.", + get_subscriber_model + ) + + @override_settings( + DJSTRIPE_SUBSCRIBER_MODEL='testapp.NoEmailOrganization', + DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=(lambda request: request.org) + ) def test_no_email_model(self): - self.assertRaisesMessage(ImproperlyConfigured, "DJSTRIPE_SUBSCRIBER_MODEL must have an email attribute.", get_subscriber_model) + self.assertRaisesMessage( + ImproperlyConfigured, + "DJSTRIPE_SUBSCRIBER_MODEL must have an email attribute.", + get_subscriber_model + ) @override_settings(DJSTRIPE_SUBSCRIBER_MODEL='testapp.Organization') def test_no_callback(self): - self.assertRaisesMessage(ImproperlyConfigured, "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK must be implemented if a DJSTRIPE_SUBSCRIBER_MODEL is defined.", get_subscriber_model) + self.assertRaisesMessage( + ImproperlyConfigured, + "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK must be implemented if a DJSTRIPE_SUBSCRIBER_MODEL is " + "defined.", + get_subscriber_model + ) @override_settings(DJSTRIPE_SUBSCRIBER_MODEL='testapp.Organization', DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK=5) def test_bad_callback(self): - self.assertRaisesMessage(ImproperlyConfigured, "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK must be callable.", get_subscriber_model) + self.assertRaisesMessage( + ImproperlyConfigured, + "DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK must be callable.", + get_subscriber_model + ) @override_settings(DJSTRIPE_TEST_CALLBACK=(lambda: "ok")) def test_get_callback_function_with_valid_func_callable(self): diff --git a/tests/test_stripe_object.py b/tests/test_stripe_object.py index c155c3f870..f9a187b4a5 100644 --- a/tests/test_stripe_object.py +++ b/tests/test_stripe_object.py @@ -13,8 +13,17 @@ from djstripe.stripe_objects import StripeObject, StripeCharField, StripeBooleanField -SIMPLE_OBJ = {'id': 'yo', 'livemode': True} -SIMPLE_OBJ_RESULT = {'stripe_id': 'yo', 'description': None, 'livemode': True, 'metadata': None, 'stripe_timestamp': None} +SIMPLE_OBJ = { + 'id': 'yo', + 'livemode': True +} +SIMPLE_OBJ_RESULT = { + 'stripe_id': 'yo', + 'description': None, + 'livemode': True, + 'metadata': None, + 'stripe_timestamp': None +} class StripeObjectExceptionsTest(TestCase): diff --git a/tests/test_subscription.py b/tests/test_subscription.py index 595848bd72..5b3577bd29 100644 --- a/tests/test_subscription.py +++ b/tests/test_subscription.py @@ -30,13 +30,17 @@ def test_str(self, customer_retrieve_mock, plan_retreive_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) - self.assertEqual("".format( - current_period_start=subscription.current_period_start, - current_period_end=subscription.current_period_end, - status=subscription.status, - quantity=subscription.quantity, - stripe_id=subscription.stripe_id - ), str(subscription)) + self.assertEqual( + "".format( + current_period_start=subscription.current_period_start, + current_period_end=subscription.current_period_end, + status=subscription.status, + quantity=subscription.quantity, + stripe_id=subscription.stripe_id + ), + str(subscription) + ) @patch("stripe.Plan.retrieve", return_value=deepcopy(FAKE_PLAN)) @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER)) @@ -233,7 +237,8 @@ def test_cancel_at_period_end(self, customer_retrieve_mock, subscription_retriev @patch("stripe.Plan.retrieve", return_value=deepcopy(FAKE_PLAN)) @patch("stripe.Subscription.retrieve") @patch("stripe.Customer.retrieve", return_value=deepcopy(FAKE_CUSTOMER)) - def test_cancel_during_trial_sets_at_period_end(self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock): + def test_cancel_during_trial_sets_at_period_end(self, customer_retrieve_mock, subscription_retrieve_mock, + plan_retrieve_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) subscription.trial_end = timezone.now() + timezone.timedelta(days=7) diff --git a/tests/test_sync.py b/tests/test_sync.py index a099155fd3..9fc147ab25 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -62,41 +62,51 @@ def test_plan_created(self, plan_create_mock): sync_plans() self.assertTrue("Plan created for test", sys.stdout.getvalue().strip()) - plan_create_mock.assert_any_call(api_key=settings.STRIPE_SECRET_KEY, - amount=1000, - interval="month", - name="Test Plan 0", - currency="usd", - id="test_id_0") - - plan_create_mock.assert_any_call(api_key=settings.STRIPE_SECRET_KEY, - amount=2500, - interval="month", - name="Test Plan 1", - currency="usd", - id="test_id") - - plan_create_mock.assert_any_call(api_key=settings.STRIPE_SECRET_KEY, - amount=5000, - interval="month", - name="Test Plan 2", - currency="usd", - id="test_id_2") - - plan_create_mock.assert_any_call(api_key=settings.STRIPE_SECRET_KEY, - amount=5000, - interval="month", - name="Test Plan 3", - currency="usd", - id="test_id_3") - - plan_create_mock.assert_any_call(api_key=settings.STRIPE_SECRET_KEY, - amount=7000, - interval="month", - name="Test Plan 4", - currency="usd", - id="test_id_4", - trial_period_days=7) + plan_create_mock.assert_any_call( + api_key=settings.STRIPE_SECRET_KEY, + amount=1000, + interval="month", + name="Test Plan 0", + currency="usd", + id="test_id_0" + ) + + plan_create_mock.assert_any_call( + api_key=settings.STRIPE_SECRET_KEY, + amount=2500, + interval="month", + name="Test Plan 1", + currency="usd", + id="test_id" + ) + + plan_create_mock.assert_any_call( + api_key=settings.STRIPE_SECRET_KEY, + amount=5000, + interval="month", + name="Test Plan 2", + currency="usd", + id="test_id_2" + ) + + plan_create_mock.assert_any_call( + api_key=settings.STRIPE_SECRET_KEY, + amount=5000, + interval="month", + name="Test Plan 3", + currency="usd", + id="test_id_3" + ) + + plan_create_mock.assert_any_call( + api_key=settings.STRIPE_SECRET_KEY, + amount=7000, + interval="month", + name="Test Plan 4", + currency="usd", + id="test_id_4", + trial_period_days=7 + ) self.assertEqual(5, plan_create_mock.call_count) diff --git a/tests/test_transfer.py b/tests/test_transfer.py index e9430b2d24..9fef5ffaf2 100644 --- a/tests/test_transfer.py +++ b/tests/test_transfer.py @@ -30,7 +30,10 @@ def test_update_transfer(self, event_retrieve_mock, transfer_retrieve_mock): fake_event_updated["data"]["object"]["status"] = "fish" event_retrieve_mock.side_effect = [fake_event_created, fake_event_updated] - transfer_retrieve_mock.side_effect = [fake_event_created["data"]["object"], fake_event_updated["data"]["object"]] + transfer_retrieve_mock.side_effect = [ + fake_event_created["data"]["object"], + fake_event_updated["data"]["object"] + ] # Create transfer created_event = Event.sync_from_stripe_data(fake_event_created) diff --git a/tests/test_urls.py b/tests/test_urls.py index 208e79cb95..df0fcb7c7e 100644 --- a/tests/test_urls.py +++ b/tests/test_urls.py @@ -14,22 +14,16 @@ def empty_view(request): urlpatterns = [ url(r'^home/', empty_view, name="home"), url(r'^admin/', include(admin.site.urls)), - url(r'^djstripe/', include('djstripe.urls', - namespace="djstripe", app_name="djstripe")), + url(r'^djstripe/', include('djstripe.urls', namespace="djstripe", app_name="djstripe")), url(r'^testapp/', include('tests.apps.testapp.urls')), url(r'^__debug__/', include('tests.apps.testapp.urls')), url( r'^testapp_namespaced/', - include('tests.apps.testapp_namespaced.urls', - namespace="testapp_namespaced", - app_name="testapp_namespaced")), + include('tests.apps.testapp_namespaced.urls', namespace="testapp_namespaced", app_name="testapp_namespaced") + ), # Represents protected content url(r'^testapp_content/', include('tests.apps.testapp_content.urls')), # For testing fnmatches - url( - r"test_fnmatch/extra_text/$", - empty_view, - name="test_fnmatch" - ), + url(r"test_fnmatch/extra_text/$", empty_view, name="test_fnmatch"), ] diff --git a/tests/test_views.py b/tests/test_views.py index b2ca310af9..f702fa937e 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -28,7 +28,11 @@ class AccountViewTest(TestCase): def setUp(self): self.url = reverse("djstripe:account") - self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com", password="password") + self.user = get_user_model().objects.create_user( + username="pydanny", + email="pydanny@gmail.com", + password="password" + ) self.assertTrue(self.client.login(username="pydanny", password="password")) Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN)) @@ -64,7 +68,11 @@ class ChangeCardViewTest(TestCase): def setUp(self): self.url = reverse("djstripe:change_card") - self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com", password="password") + self.user = get_user_model().objects.create_user( + username="pydanny", + email="pydanny@gmail.com", + password="password" + ) self.assertTrue(self.client.login(username="pydanny", password="password")) @patch("stripe.Customer.create", return_value=deepcopy(FAKE_CUSTOMER)) @@ -77,7 +85,8 @@ def test_get(self, stripe_create_customer_mock): @patch("djstripe.models.Customer.send_invoice", autospec=True) @patch("djstripe.models.Customer.add_card", autospec=True) @patch("stripe.Customer.create", return_value=deepcopy(FAKE_CUSTOMER)) - def test_post_new_card(self, stripe_customer_create_mock, add_card_mock, send_invoice_mock, retry_unpaid_invoices_mock): + def test_post_new_card(self, stripe_customer_create_mock, add_card_mock, send_invoice_mock, + retry_unpaid_invoices_mock): self.client.post(self.url, {"stripe_token": "alpha"}) add_card_mock.assert_called_once_with(self.user.customer, "alpha") send_invoice_mock.assert_called_with(self.user.customer) @@ -147,7 +156,11 @@ class HistoryViewTest(TestCase): def setUp(self): self.url = reverse("djstripe:history") - self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com", password="password") + self.user = get_user_model().objects.create_user( + username="pydanny", + email="pydanny@gmail.com", + password="password" + ) self.assertTrue(self.client.login(username="pydanny", password="password")) @patch("stripe.Customer.create", return_value=deepcopy(FAKE_CUSTOMER)) @@ -169,7 +182,11 @@ class SyncHistoryViewTest(TestCase): def setUp(self): self.url = reverse("djstripe:sync_history") - self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com", password="password") + self.user = get_user_model().objects.create_user( + username="pydanny", + email="pydanny@gmail.com", + password="password" + ) self.assertTrue(self.client.login(username="pydanny", password="password")) @patch("djstripe.views.sync_subscriber", new_callable=PropertyMock, return_value=PropertyMock(subscriber="pie")) @@ -186,7 +203,11 @@ class ConfirmFormViewTest(TestCase): def setUp(self): self.plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN)) self.url = reverse("djstripe:confirm", kwargs={"plan_id": self.plan.id}) - self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com", password="password") + self.user = get_user_model().objects.create_user( + username="pydanny", + email="pydanny@gmail.com", + password="password" + ) self.assertTrue(self.client.login(username="pydanny", password="password")) def test_get_form_current_plan(self): @@ -247,7 +268,11 @@ class ChangePlanViewTest(TestCase): def setUp(self): self.url = reverse("djstripe:change_plan") - self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com", password="password") + self.user = get_user_model().objects.create_user( + username="pydanny", + email="pydanny@gmail.com", + password="password" + ) self.assertTrue(self.client.login(username="pydanny", password="password")) def test_post_form_invalid(self): @@ -264,7 +289,10 @@ def test_post_new_sub_no_proration(self): response = self.client.post(self.url) self.assertEqual(200, response.status_code) self.assertIn("form", response.context) - self.assertIn("You must already be subscribed to a plan before you can change it.", response.context["form"].errors["__all__"]) + self.assertIn( + "You must already be subscribed to a plan before you can change it.", + response.context["form"].errors["__all__"] + ) @patch("djstripe.models.Subscription.update", autospec=True) def test_change_sub_no_proration(self, subscription_update_mock): @@ -359,7 +387,11 @@ class CancelSubscriptionViewTest(TestCase): def setUp(self): self.plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN)) self.url = reverse("djstripe:cancel_subscription") - self.user = get_user_model().objects.create_user(username="pydanny", email="pydanny@gmail.com", password="password") + self.user = get_user_model().objects.create_user( + username="pydanny", + email="pydanny@gmail.com", + password="password" + ) self.assertTrue(self.client.login(username="pydanny", password="password")) @patch("djstripe.models.Subscription.cancel") diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py index add7552f56..5cedd84b00 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -7,8 +7,8 @@ """ -from copy import deepcopy from collections import defaultdict +from copy import deepcopy import json from django.core.urlresolvers import reverse @@ -41,9 +41,8 @@ def test_webhook_with_transfer_event(self, event_retrieve_mock, transfer_retriev @patch.object(views.djstripe_settings, 'WEBHOOK_EVENT_CALLBACK', return_value=(lambda event: event.process())) @patch("stripe.Transfer.retrieve", return_value=deepcopy(FAKE_TRANSFER)) @patch("stripe.Event.retrieve") - def test_webhook_with_custom_callback(self, - event_retrieve_mock, transfer_retrieve_mock, - webhook_event_callback_mock): + def test_webhook_with_custom_callback(self, event_retrieve_mock, transfer_retrieve_mock, + webhook_event_callback_mock): fake_event = deepcopy(FAKE_EVENT_TRANSFER_CREATED) event_retrieve_mock.return_value = fake_event