Skip to content
This repository has been archived by the owner on Sep 3, 2024. It is now read-only.

Commit

Permalink
Add charge_immediately option to SubscriptionRestView
Browse files Browse the repository at this point in the history
- Add to docs
- Add to tests, better organization for tests
- Adhere to flake8 styling
  • Loading branch information
aleccool213 committed Jul 8, 2016
1 parent a711b80 commit 7e16032
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 16 deletions.
1 change: 1 addition & 0 deletions djstripe/contrib/rest_framework/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ class CreateSubscriptionSerializer(serializers.Serializer):

stripe_token = serializers.CharField(max_length=200)
plan = serializers.CharField(max_length=50)
charge_immediately = serializers.NullBooleanField(required=False)
14 changes: 11 additions & 3 deletions djstripe/contrib/rest_framework/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,21 @@ def post(self, request, format=None):

if serializer.is_valid():
try:
customer, _created = Customer.get_or_create(subscriber=subscriber_request_callback(self.request))
customer, created = Customer.get_or_create(
subscriber=subscriber_request_callback(self.request)
)
customer.add_card(serializer.data["stripe_token"])
customer.subscribe(serializer.data["plan"])
customer.subscribe(
serializer.data["plan"],
serializer.data.get("charge_immediately", True)
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
except:
# TODO: Better error messages
return Response("Something went wrong processing the payment.", status=status.HTTP_400_BAD_REQUEST)
return Response(
"Something went wrong processing the payment.",
status=status.HTTP_400_BAD_REQUEST
)

return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Expand Down
2 changes: 2 additions & 0 deletions docs/cookbook.rst
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ DELETE will cancel the current subscription, based on the settings.
- input
- stripe_token (string)
- plan (string)
- charge_immediately (boolean, optional)
- Does not send an invoice to the Customer immediately

- output (201)
- stripe_token (string)
Expand Down
77 changes: 64 additions & 13 deletions tests/test_contrib/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ def setUp(self):
@patch("djstripe.models.Customer.add_card", autospec=True)
@patch("stripe.Customer.create", return_value=deepcopy(FAKE_CUSTOMER))
def test_create_subscription(self, stripe_customer_create_mock, add_card_mock, subscribe_mock):
"""Test a POST to the SubscriptionRestView.
Should:
- Create a Customer object
- Add a card to the Customer object
- Subcribe the Customer to a plan
"""
self.assertEqual(0, Customer.objects.count())
data = {
"plan": "test0",
Expand All @@ -45,14 +52,38 @@ def test_create_subscription(self, stripe_customer_create_mock, add_card_mock, s
response = self.client.post(self.url, data)
self.assertEqual(1, Customer.objects.count())
add_card_mock.assert_called_once_with(self.user.customer, "cake")
subscribe_mock.assert_called_once_with(self.user.customer, "test0")
subscribe_mock.assert_called_once_with(self.user.customer, "test0", True)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data, data)

@patch("djstripe.models.Customer.subscribe", autospec=True)
@patch("djstripe.models.Customer.add_card", autospec=True)
@patch("stripe.Customer.create", return_value=deepcopy(FAKE_CUSTOMER))
def test_create_subscription_charge_immediately(self, stripe_customer_create_mock, add_card_mock, subscribe_mock):
"""Test a POST to the SubscriptionRestView.
Should be able to accept an charge_immediately.
This will not send an invoice to the customer on subscribe.
"""
self.assertEqual(0, Customer.objects.count())
data = {
"plan": "test0",
"stripe_token": "cake",
"charge_immediately": False,
}
response = self.client.post(self.url, data)
subscribe_mock.assert_called_once_with(self.user.customer, "test0", False)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data, data)

@patch("djstripe.models.Customer.subscribe", autospec=True)
@patch("djstripe.models.Customer.add_card", autospec=True)
@patch("stripe.Customer.create", return_value=deepcopy(FAKE_CUSTOMER))
def test_create_subscription_exception(self, stripe_customer_create_mock, add_card_mock, subscribe_mock):
"""Test a POST to the SubscriptionRestView.
Should return a 400 when an Exception is raised.
"""
subscribe_mock.side_effect = Exception
data = {
"plan": "test0",
Expand All @@ -61,11 +92,24 @@ def test_create_subscription_exception(self, stripe_customer_create_mock, add_ca
response = self.client.post(self.url, data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_get_no_content_for_subscription(self):
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
def test_create_subscription_incorrect_data(self):
"""Test a POST to the SubscriptionRestView.
Should return a 400 when a the serializer is invalid.
"""
self.assertEqual(0, Customer.objects.count())
data = {
"foo": "bar",
}
response = self.client.post(self.url, data)
self.assertEqual(0, Customer.objects.count())
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_get_subscription(self):
"""Test a GET to the SubscriptionRestView.
Should return the correct data.
"""
Customer.objects.create(subscriber=self.user, stripe_id=FAKE_CUSTOMER["id"], currency="usd")
plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN))
subscription = Subscription.sync_from_stripe_data(deepcopy(FAKE_SUBSCRIPTION))
Expand All @@ -76,8 +120,20 @@ def test_get_subscription(self):
self.assertEqual(response.data['status'], subscription.status)
self.assertEqual(response.data['cancel_at_period_end'], subscription.cancel_at_period_end)

def test_get_no_content_for_subscription(self):
"""Test a GET to the SubscriptionRestView.
Should return a 204 when an exception is raised.
"""
response = self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

@patch("djstripe.models.Subscription.cancel")
def test_cancel_subscription(self, cancel_subscription_mock):
"""Test a DELETE to the SubscriptionRestView.
Should cancel a Customer objects subscription.
"""
def _cancel_sub(*args, **kwargs):
subscription = Subscription.objects.first()
subscription.status = Subscription.STATUS_CANCELED
Expand Down Expand Up @@ -108,16 +164,11 @@ def _cancel_sub(*args, **kwargs):
self.assertTrue(self.user.is_authenticated())

def test_cancel_subscription_exception(self):
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
"""Test a DELETE to the SubscriptionRestView.
def test_create_subscription_incorrect_data(self):
self.assertEqual(0, Customer.objects.count())
data = {
"foo": "bar",
}
response = self.client.post(self.url, data)
self.assertEqual(0, Customer.objects.count())
Should return a 400 when an exception is raised.
"""
response = self.client.delete(self.url)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)


Expand Down

0 comments on commit 7e16032

Please sign in to comment.