From d87bfa6a7b3ed7275cd5a10b0d39dc04903843df Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Wed, 17 Oct 2018 13:22:28 +0200 Subject: [PATCH 1/5] Add VAT ID field for Gold User --- readthedocs/gold/forms.py | 4 +++- readthedocs/gold/models.py | 1 + readthedocs/payments/forms.py | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/readthedocs/gold/forms.py b/readthedocs/gold/forms.py index 12d1d364567..f165645a490 100644 --- a/readthedocs/gold/forms.py +++ b/readthedocs/gold/forms.py @@ -47,12 +47,14 @@ def validate_stripe(self): subscription = self.get_subscription() self.instance.stripe_id = subscription.customer self.instance.subscribed = True + self.instance.business_vat_id = self.cleaned_data['business_vat_id'] def get_customer_kwargs(self): return { 'description': self.customer.get_full_name() or self.customer.username, 'email': self.customer.email, - 'id': self.instance.stripe_id or None + 'id': self.instance.stripe_id or None, + 'business_vat_id': self.cleaned_data['business_vat_id'] or None, } def get_subscription(self): diff --git a/readthedocs/gold/models.py b/readthedocs/gold/models.py index c07aee2a92c..e55bf412d56 100644 --- a/readthedocs/gold/models.py +++ b/readthedocs/gold/models.py @@ -42,6 +42,7 @@ class GoldUser(models.Model): last_4_card_digits = models.CharField(max_length=4) stripe_id = models.CharField(max_length=255) subscribed = models.BooleanField(default=False) + business_vat_id = models.CharField(max_length=128, null=True, blank=True) def __str__(self): return 'Gold Level %s for %s' % (self.level, self.user) diff --git a/readthedocs/payments/forms.py b/readthedocs/payments/forms.py index 983dfe638f4..19796b2e809 100644 --- a/readthedocs/payments/forms.py +++ b/readthedocs/payments/forms.py @@ -71,6 +71,11 @@ class StripeModelForm(forms.ModelForm): :cvar cc_cvv: Credit card security code field, used only by Stripe.js """ + business_vat_id = forms.CharField( + label=_('VAT ID number'), + required=False, + ) + # Stripe token input from Stripe.js stripe_token = forms.CharField( required=False, From f9e0578a6e1b6b23c30994ca9b35b484ba8959cb Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 22 Oct 2018 14:23:50 +0200 Subject: [PATCH 2/5] Send VAT to stripe only when it's defined --- readthedocs/gold/forms.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/readthedocs/gold/forms.py b/readthedocs/gold/forms.py index f165645a490..248e50cc276 100644 --- a/readthedocs/gold/forms.py +++ b/readthedocs/gold/forms.py @@ -50,12 +50,17 @@ def validate_stripe(self): self.instance.business_vat_id = self.cleaned_data['business_vat_id'] def get_customer_kwargs(self): - return { + data = { 'description': self.customer.get_full_name() or self.customer.username, 'email': self.customer.email, 'id': self.instance.stripe_id or None, - 'business_vat_id': self.cleaned_data['business_vat_id'] or None, } + business_vat_id = self.cleaned_data.get('business_vat_id') + if business_vat_id: + data.update({ + 'business_vat_id': self.cleaned_data['business_vat_id'], + }) + return data def get_subscription(self): customer = self.get_customer() From b3f822c105d54531cdf5bb6afd636fb31ed60bc6 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 22 Oct 2018 14:24:20 +0200 Subject: [PATCH 3/5] Migration for VAT field --- .../gold/migrations/0003_add_vat_id.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 readthedocs/gold/migrations/0003_add_vat_id.py diff --git a/readthedocs/gold/migrations/0003_add_vat_id.py b/readthedocs/gold/migrations/0003_add_vat_id.py new file mode 100644 index 00000000000..083a60e8cc6 --- /dev/null +++ b/readthedocs/gold/migrations/0003_add_vat_id.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2018-10-22 07:13 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('gold', '0002_rename_last_4_digits'), + ] + + operations = [ + migrations.AddField( + model_name='golduser', + name='business_vat_id', + field=models.CharField(blank=True, max_length=128, null=True), + ), + ] From f46cbc85a4ef0d9952e710adc18dedd556ee0962 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 22 Oct 2018 14:24:29 +0200 Subject: [PATCH 4/5] Test case --- readthedocs/gold/tests/test_forms.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/readthedocs/gold/tests/test_forms.py b/readthedocs/gold/tests/test_forms.py index 4ea65403017..4618b8870fc 100644 --- a/readthedocs/gold/tests/test_forms.py +++ b/readthedocs/gold/tests/test_forms.py @@ -65,24 +65,27 @@ def test_add_subscription(self): ]) # Create user and subscription - subscription_form = GoldSubscriptionForm( - {'level': 'v1-org-5', - 'last_4_card_digits': '0000', - 'stripe_token': 'GARYBUSEY'}, - customer=self.user + subscription_form = GoldSubscriptionForm({ + 'level': 'v1-org-5', + 'last_4_card_digits': '0000', + 'stripe_token': 'GARYBUSEY', + 'business_vat_id': 'business-vat-id', + }, + customer=self.user, ) self.assertTrue(subscription_form.is_valid()) subscription = subscription_form.save() self.assertEqual(subscription.level, 'v1-org-5') self.assertEqual(subscription.stripe_id, 'cus_12345') + self.assertEqual(subscription.business_vat_id, 'business-vat-id') self.assertIsNotNone(self.user.gold) self.assertEqual(self.user.gold.first().level, 'v1-org-5') self.mocks['request'].request.assert_has_calls([ mock.call('post', '/v1/customers', - {'description': mock.ANY, 'email': mock.ANY}, + {'description': mock.ANY, 'email': mock.ANY, 'business_vat_id': 'business-vat-id'}, mock.ANY), mock.call('get', '/v1/customers/cus_12345/subscriptions', From adb9858c197467a300301863c315af8a1eac165b Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Thu, 1 Nov 2018 16:27:15 +0100 Subject: [PATCH 5/5] Migrations fixed --- .../gold/migrations/{0003_add_vat_id.py => 0004_add_vat_id.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename readthedocs/gold/migrations/{0003_add_vat_id.py => 0004_add_vat_id.py} (87%) diff --git a/readthedocs/gold/migrations/0003_add_vat_id.py b/readthedocs/gold/migrations/0004_add_vat_id.py similarity index 87% rename from readthedocs/gold/migrations/0003_add_vat_id.py rename to readthedocs/gold/migrations/0004_add_vat_id.py index 083a60e8cc6..eab1771f1a2 100644 --- a/readthedocs/gold/migrations/0003_add_vat_id.py +++ b/readthedocs/gold/migrations/0004_add_vat_id.py @@ -8,7 +8,7 @@ class Migration(migrations.Migration): dependencies = [ - ('gold', '0002_rename_last_4_digits'), + ('gold', '0003_add_missing_model_change_migrations'), ] operations = [