diff --git a/djstripe/models.py b/djstripe/models.py index f56b2b462b..8ca69306af 100644 --- a/djstripe/models.py +++ b/djstripe/models.py @@ -3013,19 +3013,24 @@ def cancel(self, at_period_end=djstripe_settings.CANCELLATION_AT_PERIOD_END): if self.trial_end and self.trial_end > timezone.now(): at_period_end = False - try: - stripe_subscription = self._api_delete(at_period_end=at_period_end) - except InvalidRequestError as exc: - if "No such subscription:" in text_type(exc): - # cancel() works by deleting the subscription. The object still - # exists in Stripe however, and can still be retrieved. - # If the subscription was already canceled (status=canceled), - # that api_retrieve() call will fail with "No such subscription". - # However, this may also happen if the subscription legitimately - # does not exist, in which case the following line will re-raise. - stripe_subscription = self.api_retrieve() - else: - six.reraise(*sys.exc_info()) + if at_period_end: + stripe_subscription = self.api_retrieve() + stripe_subscription.cancel_at_period_end = True + stripe_subscription.save() + else: + try: + stripe_subscription = self._api_delete() + except InvalidRequestError as exc: + if "No such subscription:" in text_type(exc): + # cancel() works by deleting the subscription. The object still + # exists in Stripe however, and can still be retrieved. + # If the subscription was already canceled (status=canceled), + # that api_retrieve() call will fail with "No such subscription". + # However, this may also happen if the subscription legitimately + # does not exist, in which case the following line will re-raise. + stripe_subscription = self.api_retrieve() + else: + six.reraise(*sys.exc_info()) return Subscription.sync_from_stripe_data(stripe_subscription) diff --git a/tests/test_subscription.py b/tests/test_subscription.py index e0930a35d9..92f36866fc 100644 --- a/tests/test_subscription.py +++ b/tests/test_subscription.py @@ -309,7 +309,7 @@ def test_cancel_already_canceled(self, subscription_retrieve_mock, subscription_ subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual(Subscription.objects.filter(status="canceled").count(), 0) - subscription.cancel() + subscription.cancel(at_period_end=False) self.assertEqual(Subscription.objects.filter(status="canceled").count(), 1) @patch("djstripe.models.Subscription._api_delete") @@ -320,4 +320,4 @@ def test_cancel_error_in_cancel(self, subscription_delete_mock): subscription = Subscription.sync_from_stripe_data(subscription_fake) with self.assertRaises(InvalidRequestError): - subscription.cancel() + subscription.cancel(at_period_end=False)