def test_cancel_and_reactivate( self, customer_retrieve_mock, subscription_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): current_period_end = timezone.now() + timezone.timedelta(days=7) subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) subscription.current_period_end = current_period_end subscription.save() canceled_subscription_fake = deepcopy(FAKE_SUBSCRIPTION) canceled_subscription_fake["current_period_end"] = datetime_to_unix( current_period_end ) canceled_subscription_fake["canceled_at"] = datetime_to_unix(timezone.now()) subscription_retrieve_mock.return_value = canceled_subscription_fake self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) new_subscription = subscription.cancel(at_period_end=True) self.assertEqual(new_subscription.cancel_at_period_end, True) new_subscription.reactivate() subscription_reactivate_fake = deepcopy(FAKE_SUBSCRIPTION) reactivated_subscription = Subscription.sync_from_stripe_data( subscription_reactivate_fake ) self.assertEqual(reactivated_subscription.cancel_at_period_end, False) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
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 = SubscriptionStatus.canceled subscription.canceled_at = timezone.now() subscription.ended_at = timezone.now() subscription.save() return subscription fake_cancelled_subscription = deepcopy(FAKE_SUBSCRIPTION) Subscription.sync_from_stripe_data(fake_cancelled_subscription) cancel_subscription_mock.side_effect = _cancel_sub self.assertEqual(1, Subscription.objects.count()) self.assertEqual(Subscription.objects.first().status, SubscriptionStatus.active) response = self.client.delete(self.url) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # Cancelled means flagged as cancelled, so it should still be there self.assertEqual(1, Subscription.objects.count()) self.assertEqual(Subscription.objects.first().status, SubscriptionStatus.canceled) cancel_subscription_mock.assert_called_once_with( at_period_end=djstripe_settings.CANCELLATION_AT_PERIOD_END ) self.assertTrue(self.user.is_authenticated)
def resync_subscriptions(apps, schema_editor): """ Since subscription IDs were not previously stored, 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. 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. from djstripe.models import Subscription from djstripe.context_managers import stripe_temporary_api_version with stripe_temporary_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(serializers.serialize("json", Subscription.objects.all())) Subscription.objects.all().delete() print("Re-syncing subscriptions. This may take a while.") for stripe_subscription in tqdm(iterable=Subscription.api_list(), desc="Sync", unit=" subscriptions"): subscription = Subscription.sync_from_stripe_data(stripe_subscription) if not subscription.customer: 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.")
def test_remove_all_multi_plan( self, subscription_retrieve_mock, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION_MULTI_PLAN) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertIsNone(subscription.plan) self.assertIsNone(subscription.quantity) items = subscription.items.all() self.assertEqual(2, len(items)) # Simulate a webhook received with no more plan del subscription_fake["items"]["data"][1] del subscription_fake["items"]["data"][0] subscription_fake["items"]["total_count"] = 0 subscription = Subscription.sync_from_stripe_data(subscription_fake) items = subscription.items.all() self.assertEqual(0, len(items)) self.assert_fks( subscription, expected_blank_fks=self.default_expected_blank_fks | {"djstripe.Customer.subscriber", "djstripe.Subscription.plan"}, )
def test_should_apply_to_true_stripe(self, user): customer = Customer.objects.create( stripe_id="cust_TEST", account_balance=0, delinquent=False, subscriber=user ) plan = Plan.objects.create( stripe_id="plan_TEST", amount=0, currency="USD", interval=PlanInterval.month ) subscription = Subscription( current_period_end=timezone.now() + timedelta(days=7), current_period_start=timezone.now() - timedelta(days=7), customer=customer, quantity=1, plan=plan, start=timezone.now() - timedelta(days=7), status="active" ) subscription.save() user.djstripe_customers.add(customer) assert self.tag.should_apply_to(user)
def test_cancel_and_reactivate( self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock ): current_period_end = timezone.now() + timezone.timedelta(days=7) subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) subscription.current_period_end = current_period_end subscription.save() canceled_subscription_fake = deepcopy(FAKE_SUBSCRIPTION) canceled_subscription_fake["current_period_end"] = datetime_to_unix( current_period_end ) canceled_subscription_fake["canceled_at"] = datetime_to_unix(timezone.now()) subscription_retrieve_mock.return_value = canceled_subscription_fake self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) new_subscription = subscription.cancel(at_period_end=True) self.assertEqual(new_subscription.cancel_at_period_end, True) new_subscription.reactivate() subscription_reactivate_fake = deepcopy(FAKE_SUBSCRIPTION) reactivated_subscription = Subscription.sync_from_stripe_data( subscription_reactivate_fake ) self.assertEqual(reactivated_subscription.cancel_at_period_end, False) self.assert_fks( subscription, expected_blank_fks={"djstripe.Customer.coupon", "djstripe.Plan.product"}, )
def manage_subscription(request): #First get user specific subscription; '''' user=User.objects.get(username=request.user.username) subscription = SubscriberSubscriptionDetails.objects.get(user=user) djstripes=djstripe.models.Subscription.objects.get(pk=subscription.subscription_id) cancel_my_subscription=stripe.Subscription.delete(djstripes.id) djstripe.models.Subscription.sync_from_stripe_data(cancel_my_subscription) messages.success(request,'Your subscription has been cancelled successfully') ''' user = User.objects.get(username=request.user.username) status='not subscribed' try: subscription = SubscriberSubscriptionDetails.objects.filter(user=user).latest('date_subscribed') djstripes = Subscription.objects.get(pk=subscription.subscription_id) status=djstripes.status except SubscriberSubscriptionDetails.DoesNotExist: subscription=None if request.method == 'POST': cancel_my_subscription = stripe.Subscription.delete(djstripes.id) Subscription.sync_from_stripe_data(cancel_my_subscription) messages.success(request, 'Your subscription has been cancelled successfully') return render(request,'subscriber/manage_subscriptions.html',{'s_status':status})
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 = SubscriptionStatus.canceled subscription.canceled_at = timezone.now() subscription.ended_at = timezone.now() subscription.save() return subscription fake_cancelled_subscription = deepcopy(FAKE_SUBSCRIPTION) Subscription.sync_from_stripe_data(fake_cancelled_subscription) cancel_subscription_mock.side_effect = _cancel_sub self.assertEqual(1, Subscription.objects.count()) self.assertEqual(Subscription.objects.first().status, SubscriptionStatus.active) response = self.client.delete(self.url) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # Cancelled means flagged as cancelled, so it should still be there self.assertEqual(1, Subscription.objects.count()) self.assertEqual(Subscription.objects.first().status, SubscriptionStatus.canceled) cancel_subscription_mock.assert_called_once_with( at_period_end=djstripe_settings.CANCELLATION_AT_PERIOD_END) self.assertTrue(self.user.is_authenticated)
def test_cancel_at_period_end(self, cancel_subscription_mock, customer_retrieve_mock): Subscription.sync_from_stripe_data(FAKE_SUBSCRIPTION) response = self.client.post(self.url) cancel_subscription_mock.assert_called_once_with(at_period_end=True) self.assertRedirects(response, reverse("home")) self.assertTrue(self.user.is_authenticated)
def test_cancel_at_period_end(self, cancel_subscription_mock): Customer.objects.create(subscriber=self.user, stripe_id=FAKE_CUSTOMER["id"], livemode=False) Subscription.sync_from_stripe_data(FAKE_SUBSCRIPTION) response = self.client.post(self.url) cancel_subscription_mock.assert_called_once_with(at_period_end=True) self.assertRedirects(response, reverse("home")) self.assertTrue(self.user.is_authenticated())
def test_cancel_next_url(self, cancel_subscription_mock, customer_retrieve_mock): Subscription.sync_from_stripe_data(FAKE_SUBSCRIPTION) response = self.client.post(self.url + "?next=/test") self.assertEqual(response.status_code, 302) self.assertEqual(response.url, "/test") self.assertTrue(get_user(self.client).is_anonymous)
def test_remove_all_multi_plan( self, subscription_retrieve_mock, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, invoice_retrieve_mock, paymentintent_retrieve_mock, paymentmethod_retrieve_mock, charge_retrieve_mock, balance_transaction_retrieve_mock, ): # delete pydanny customer as that causes issues with Invoice and Latest_invoice FKs self.customer.delete() fake_payment_intent = deepcopy(FAKE_PAYMENT_INTENT_II) fake_payment_intent["invoice"] = FAKE_INVOICE_II["id"] paymentintent_retrieve_mock.return_value = fake_payment_intent fake_subscription = deepcopy(FAKE_SUBSCRIPTION_MULTI_PLAN) fake_subscription["latest_invoice"] = FAKE_INVOICE_II["id"] subscription_retrieve_mock.return_value = fake_subscription fake_charge = deepcopy(FAKE_CHARGE_II) fake_charge["payment_method"] = FAKE_PAYMENT_METHOD_II["id"] charge_retrieve_mock.return_value = fake_charge # create invoice fake_invoice = deepcopy(FAKE_INVOICE_II) Invoice.sync_from_stripe_data(fake_invoice) subscription = Subscription.sync_from_stripe_data(fake_subscription) self.assertIsNone(subscription.plan) self.assertIsNone(subscription.quantity) items = subscription.items.all() self.assertEqual(2, len(items)) # Simulate a webhook received with no more plan del fake_subscription["items"]["data"][1] del fake_subscription["items"]["data"][0] fake_subscription["items"]["total_count"] = 0 subscription = Subscription.sync_from_stripe_data(fake_subscription) items = subscription.items.all() self.assertEqual(0, len(items)) self.assert_fks( subscription, expected_blank_fks=self.default_expected_blank_fks | { "djstripe.Customer.subscriber", "djstripe.Subscription.plan", }, )
def test_cancel_next_url(self, cancel_subscription_mock): Customer.objects.create(subscriber=self.user, stripe_id=FAKE_CUSTOMER["id"], livemode=False) Subscription.sync_from_stripe_data(FAKE_SUBSCRIPTION) response = self.client.post(self.url + "?next=/test") self.assertEqual(response.status_code, 302) self.assertEqual(response.url, "/test") self.assertTrue(get_user(self.client).is_anonymous)
def test_update_multi_plan( self, subscription_retrieve_mock, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION_MULTI_PLAN) subscription_fake["latest_invoice"] = FAKE_INVOICE["id"] subscription_retrieve_mock.return_value = subscription_fake subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertIsNone(subscription.plan) self.assertIsNone(subscription.quantity) items = subscription.items.all() self.assertEqual(2, len(items)) # Simulate a webhook received with one plan that has been removed del subscription_fake["items"]["data"][1] subscription_fake["items"]["total_count"] = 1 subscription = Subscription.sync_from_stripe_data(subscription_fake) items = subscription.items.all() self.assertEqual(1, len(items)) # delete pydanny customer as that causes issues with Invoice and Latest_invoice FKs self.customer.delete() self.assert_fks( subscription, expected_blank_fks=( self.default_expected_blank_fks | { "djstripe.Customer.subscriber", "djstripe.Subscription.plan", "djstripe.Charge.latest_upcominginvoice (related name)", "djstripe.Charge.application_fee", "djstripe.Charge.dispute", "djstripe.Charge.on_behalf_of", "djstripe.Charge.source_transfer", "djstripe.Charge.transfer", "djstripe.PaymentIntent.upcominginvoice (related name)", "djstripe.PaymentIntent.on_behalf_of", "djstripe.PaymentIntent.payment_method", "djstripe.Invoice.default_payment_method", "djstripe.Invoice.default_source", "djstripe.Invoice.charge", "djstripe.Invoice.customer", "djstripe.Invoice.payment_intent", "djstripe.Invoice.subscription", }), )
def test_extend( self, customer_retrieve_mock, subscription_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription_fake["current_period_end"] = datetime_to_unix( timezone.now() - timezone.timedelta(days=20) ) subscription_retrieve_mock.return_value = subscription_fake subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertFalse(subscription in self.customer.active_subscriptions) self.assertEqual(self.customer.active_subscriptions.count(), 0) delta = timezone.timedelta(days=30) extended_subscription = subscription.extend(delta) self.assertNotEqual(None, extended_subscription.trial_end) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
def test_upcoming_invoice_with_subscription( self, invoice_upcoming_mock, subscription_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, invoice_retrieve_mock, payment_intent_retrieve_mock, paymentmethod_card_retrieve_mock, charge_retrieve_mock, balance_transaction_retrieve_mock, ): # create invoice for latest_invoice in subscription to work. Invoice.sync_from_stripe_data(deepcopy(FAKE_INVOICE)) invoice = Invoice.upcoming(subscription=Subscription( id=FAKE_SUBSCRIPTION["id"])) self.assertIsNotNone(invoice) self.assertIsNone(invoice.id) self.assertIsNone(invoice.save()) subscription_retrieve_mock.assert_called_once_with( api_key=ANY, expand=ANY, id=FAKE_SUBSCRIPTION["id"], stripe_account=None) plan_retrieve_mock.assert_not_called() self.assertIsNotNone(invoice.plan) self.assertEqual(FAKE_PLAN["id"], invoice.plan.id)
def test_cancel_at_period_end(self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock): current_period_end = timezone.now() + timezone.timedelta(days=7) subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) subscription.current_period_end = current_period_end subscription.save() canceled_subscription_fake = deepcopy(FAKE_SUBSCRIPTION) canceled_subscription_fake["current_period_end"] = datetime_to_unix(current_period_end) canceled_subscription_fake["canceled_at"] = datetime_to_unix(timezone.now()) subscription_retrieve_mock.return_value = canceled_subscription_fake # retrieve().delete() self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) self.assertEqual(self.customer.active_subscriptions.count(), 1) self.assertTrue(subscription in self.customer.active_subscriptions) new_subscription = subscription.cancel(at_period_end=True) self.assertEqual(self.customer.active_subscriptions.count(), 1) self.assertTrue(new_subscription in self.customer.active_subscriptions) self.assertEqual(SubscriptionStatus.active, new_subscription.status) self.assertEqual(True, new_subscription.cancel_at_period_end) self.assertNotEqual(new_subscription.canceled_at, new_subscription.ended_at) self.assertTrue(new_subscription.is_valid()) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription())
def test_sync_from_stripe_data2(self, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION_II) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assert_fks(subscription, expected_blank_fks=self.default_expected_blank_fks)
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) subscription.save() cancel_timestamp = datetime_to_unix(timezone.now()) canceled_subscription_fake = deepcopy(FAKE_SUBSCRIPTION) canceled_subscription_fake["status"] = Subscription.STATUS_CANCELED canceled_subscription_fake["canceled_at"] = cancel_timestamp canceled_subscription_fake["ended_at"] = cancel_timestamp subscription_retrieve_mock.return_value = canceled_subscription_fake # retrieve().delete() self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) new_subscription = subscription.cancel(at_period_end=False) self.assertEqual(Subscription.STATUS_CANCELED, new_subscription.status) self.assertEqual(False, new_subscription.cancel_at_period_end) self.assertEqual(new_subscription.canceled_at, new_subscription.ended_at) self.assertFalse(new_subscription.is_valid()) self.assertFalse(self.customer.has_active_subscription()) self.assertFalse(self.customer.has_any_active_subscription())
def test_cancel_already_canceled( self, subscription_retrieve_mock, product_retrieve_mock, subscription_delete_mock, ): subscription_delete_mock.side_effect = InvalidRequestError( "No such subscription: sub_xxxx", "blah") subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual( Subscription.objects.filter(status="canceled").count(), 0) subscription.cancel(at_period_end=False) self.assertEqual( Subscription.objects.filter(status="canceled").count(), 1) self.assert_fks( subscription, expected_blank_fks={ "djstripe.Customer.coupon", "djstripe.Subscription.pending_setup_intent", }, )
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( str(subscription), "{email} on {plan}".format(email=self.user.email, plan=str(subscription.plan)) )
def test_cancel_at_period_end(self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock): current_period_end = timezone.now() + timezone.timedelta(days=7) subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) subscription.current_period_end = current_period_end subscription.save() canceled_subscription_fake = deepcopy(FAKE_SUBSCRIPTION) canceled_subscription_fake["current_period_end"] = datetime_to_unix( current_period_end) canceled_subscription_fake["canceled_at"] = datetime_to_unix( timezone.now()) subscription_retrieve_mock.return_value = canceled_subscription_fake # retrieve().delete() self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) self.assertEquals(self.customer.active_subscriptions.count(), 1) self.assertTrue(subscription in self.customer.active_subscriptions) new_subscription = subscription.cancel(at_period_end=True) self.assertEquals(self.customer.active_subscriptions.count(), 1) self.assertTrue(new_subscription in self.customer.active_subscriptions) self.assertEqual(Subscription.STATUS_ACTIVE, new_subscription.status) self.assertEqual(True, new_subscription.cancel_at_period_end) self.assertNotEqual(new_subscription.canceled_at, new_subscription.ended_at) self.assertTrue(new_subscription.is_valid()) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription())
def test_sync_metered_plan( self, subscription_retrieve_mock, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION_METERED) self.assertNotIn( "quantity", subscription_fake["items"]["data"], "Expect Metered plan SubscriptionItem to have no quantity", ) subscription = Subscription.sync_from_stripe_data(subscription_fake) items = subscription.items.all() self.assertEqual(1, len(items)) item = items[0] self.assertEqual(subscription.quantity, 1) # Note that subscription.quantity is 1, # but item.quantity isn't set on metered plans self.assertIsNone(item.quantity) self.assertEqual(item.plan.id, FAKE_PLAN_METERED["id"]) self.assert_fks(subscription, expected_blank_fks=self.default_expected_blank_fks)
def test_extend_with_trial( self, customer_retrieve_mock, subscription_retrieve_mock, product_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=5) subscription.save() delta = timezone.timedelta(days=30) new_trial_end = subscription.trial_end + delta extended_subscription = subscription.extend(delta) self.assertEqual(new_trial_end.replace(microsecond=0), extended_subscription.trial_end) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) self.assert_fks( subscription, expected_blank_fks={ "djstripe.Customer.coupon", "djstripe.Subscription.pending_setup_intent", }, )
def test_update_with_plan_model( self, customer_retrieve_mock, subscription_retrieve_mock, subscription_modify_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) new_plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN_II)) self.assertEqual(FAKE_PLAN["id"], subscription.plan.id) # Update the Subscription's plan subscription_updated = deepcopy(FAKE_SUBSCRIPTION) subscription_updated["plan"] = deepcopy(FAKE_PLAN_II) subscription_modify_mock.return_value = subscription_updated new_subscription = subscription.update(plan=new_plan) self.assertEqual(FAKE_PLAN_II["id"], new_subscription.plan.id) self.assert_fks(subscription, expected_blank_fks=self.default_expected_blank_fks) self.assert_fks(new_plan, expected_blank_fks={})
def test_update_set_empty_value( self, customer_retrieve_mock, subscription_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription_fake.update({"tax_percent": Decimal(20.0)}) subscription_retrieve_mock.return_value = subscription_fake subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual(Decimal(20.0), subscription.tax_percent) new_subscription = subscription.update(tax_percent=Decimal(0.0)) self.assertEqual(Decimal(0.0), new_subscription.tax_percent) self.assert_fks( subscription, expected_blank_fks={ "djstripe.Customer.coupon", "djstripe.Subscription.pending_setup_intent", }, )
def test_extend( self, customer_retrieve_mock, subscription_retrieve_mock, subscription_modify_mock, product_retrieve_mock, plan_retrieve_mock, ): current_period_end = timezone.now() - timezone.timedelta(days=20) subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription_fake["current_period_end"] = int( current_period_end.timestamp()) subscription_retrieve_mock.return_value = subscription_fake subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertFalse(subscription in self.customer.active_subscriptions) self.assertEqual(self.customer.active_subscriptions.count(), 0) # Extend the Subscription by 30 days delta = timezone.timedelta(days=30) subscription_updated = deepcopy(subscription_fake) subscription_updated["trial_end"] = int( (current_period_end + delta).timestamp()) subscription_modify_mock.return_value = subscription_updated extended_subscription = subscription.extend(delta) product = Product.sync_from_stripe_data(deepcopy(FAKE_PRODUCT)) self.assertNotEqual(None, extended_subscription.trial_end) self.assertTrue(self.customer.is_subscribed_to(product)) self.assertTrue(self.customer.has_any_active_subscription()) self.assert_fks(subscription, expected_blank_fks=self.default_expected_blank_fks)
def test_cancel_during_trial_sets_at_period_end( self, customer_retrieve_mock, subscription_retrieve_mock, product_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) subscription.save() cancel_timestamp = datetime_to_unix(timezone.now()) canceled_subscription_fake = deepcopy(FAKE_SUBSCRIPTION) canceled_subscription_fake["status"] = SubscriptionStatus.canceled canceled_subscription_fake["canceled_at"] = cancel_timestamp canceled_subscription_fake["ended_at"] = cancel_timestamp subscription_retrieve_mock.return_value = ( canceled_subscription_fake ) # retrieve().delete() self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) new_subscription = subscription.cancel(at_period_end=False) self.assertEqual(SubscriptionStatus.canceled, new_subscription.status) self.assertEqual(False, new_subscription.cancel_at_period_end) self.assertEqual(new_subscription.canceled_at, new_subscription.ended_at) self.assertFalse(new_subscription.is_valid()) self.assertFalse(self.customer.has_active_subscription()) self.assertFalse(self.customer.has_any_active_subscription()) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
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) subscription.save() cancel_timestamp = datetime_to_unix(timezone.now()) canceled_subscription_fake = deepcopy(FAKE_SUBSCRIPTION) canceled_subscription_fake["status"] = SubscriptionStatus.canceled canceled_subscription_fake["canceled_at"] = cancel_timestamp canceled_subscription_fake["ended_at"] = cancel_timestamp subscription_retrieve_mock.return_value = ( canceled_subscription_fake ) # retrieve().delete() self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) new_subscription = subscription.cancel(at_period_end=False) self.assertEqual(SubscriptionStatus.canceled, new_subscription.status) self.assertEqual(False, new_subscription.cancel_at_period_end) self.assertEqual(new_subscription.canceled_at, new_subscription.ended_at) self.assertFalse(new_subscription.is_valid()) self.assertFalse(self.customer.has_active_subscription()) self.assertFalse(self.customer.has_any_active_subscription()) self.assert_fks( subscription, expected_blank_fks={"djstripe.Customer.coupon", "djstripe.Plan.product"}, )
def test_update_with_plan_model( self, customer_retrieve_mock, subscription_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) new_plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN_II)) self.assertEqual(FAKE_PLAN["id"], subscription.plan.id) new_subscription = subscription.update(plan=new_plan) self.assertEqual(FAKE_PLAN_II["id"], new_subscription.plan.id) self.assert_fks( subscription, expected_blank_fks={ "djstripe.Customer.coupon", "djstripe.Subscription.pending_setup_intent", }, ) self.assert_fks(new_plan, expected_blank_fks={})
def test_sync_metered_plan( self, subscription_retrieve_mock, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION_METERED) self.assertNotIn( "quantity", subscription_fake["items"]["data"], "Expect Metered plan SubscriptionItem to have no quantity", ) subscription = Subscription.sync_from_stripe_data(subscription_fake) items = subscription.items.all() self.assertEqual(1, len(items)) item = items[0] self.assertEqual(subscription.quantity, 1) # Note that subscription.quantity is 1, but item.quantity isn't set on metered plans, # it probably should be nullable self.assertEqual(item.quantity, 0) self.assertEqual(item.plan.id, FAKE_PLAN_METERED["id"]) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
def test_extend( self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription_fake["current_period_end"] = datetime_to_unix( timezone.now() - timezone.timedelta(days=20) ) subscription_retrieve_mock.return_value = subscription_fake subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertFalse(subscription in self.customer.active_subscriptions) self.assertEqual(self.customer.active_subscriptions.count(), 0) delta = timezone.timedelta(days=30) extended_subscription = subscription.extend(delta) self.assertNotEqual(None, extended_subscription.trial_end) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) self.assert_fks( subscription, expected_blank_fks={"djstripe.Customer.coupon", "djstripe.Plan.product"}, )
def test_extend_with_trial( self, customer_retrieve_mock, subscription_retrieve_mock, product_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=5) subscription.save() delta = timezone.timedelta(days=30) new_trial_end = subscription.trial_end + delta extended_subscription = subscription.extend(delta) self.assertEqual(new_trial_end.replace(microsecond=0), extended_subscription.trial_end) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.is_subscribed_to(FAKE_PRODUCT["id"])) self.assertTrue(self.customer.has_any_active_subscription()) self.assert_fks(subscription, expected_blank_fks=self.default_expected_blank_fks)
def test_is_status_temporarily_current(self, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) subscription.canceled_at = timezone.now() + timezone.timedelta(days=7) subscription.current_period_end = timezone.now() + timezone.timedelta( days=7) subscription.cancel_at_period_end = True subscription.save() self.assertTrue(subscription.is_status_current()) self.assertTrue(subscription.is_status_temporarily_current()) self.assertTrue(subscription.is_valid()) self.assertTrue(subscription in self.customer.active_subscriptions) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription()) self.assert_fks( subscription, expected_blank_fks={ "djstripe.Customer.coupon", "djstripe.Subscription.pending_setup_intent", }, )
def test_sync_multi_plan( self, subscription_retrieve_mock, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION_MULTI_PLAN) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertIsNone(subscription.plan) self.assertIsNone(subscription.quantity) items = subscription.items.all() self.assertEqual(2, len(items)) self.assert_fks( subscription, expected_blank_fks={ "djstripe.Customer.coupon", "djstripe.Customer.subscriber", "djstripe.Subscription.plan", "djstripe.Subscription.pending_setup_intent", }, )
def test_user_has_active_subscription(self): subscription = Subscription.sync_from_stripe_data(deepcopy(FAKE_SUBSCRIPTION)) subscription.current_period_end = timezone.now() + timezone.timedelta(days=10) subscription.save() # Assert that the customer's subscription is valid self.assertTrue(subscriber_has_active_subscription(self.user))
def test_cancel_error_in_cancel(self, subscription_delete_mock): subscription_delete_mock.side_effect = InvalidRequestError("Unexpected error", "blah") subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) with self.assertRaises(InvalidRequestError): subscription.cancel()
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( str(subscription), "{email} on {plan}".format(email=self.user.email, plan=str(subscription.plan)))
def setUp(self): self.settings(ROOT_URLCONF=self.urlconf) self.factory = RequestFactory() self.user = get_user_model().objects.create_user(username="******", email="*****@*****.**") self.customer = Customer.sync_from_stripe_data(FAKE_CUSTOMER) self.customer.subscriber = self.user self.customer.save() self.subscription = Subscription.sync_from_stripe_data(FAKE_SUBSCRIPTION) self.middleware = SubscriptionPaymentMiddleware()
def test_update(self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual(1, subscription.quantity) new_subscription = subscription.update(quantity=4) self.assertEqual(4, new_subscription.quantity)
def test_cancel_already_canceled(self, subscription_retrieve_mock, subscription_delete_mock): subscription_delete_mock.side_effect = InvalidRequestError("No such subscription: sub_xxxx", "blah") subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual(Subscription.objects.filter(status="canceled").count(), 0) subscription.cancel() self.assertEqual(Subscription.objects.filter(status="canceled").count(), 1)
def test_extend_negative_delta(self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) with self.assertRaises(ValueError): subscription.extend(timezone.timedelta(days=-30)) self.assertFalse(self.customer.has_active_subscription()) self.assertFalse(self.customer.has_any_active_subscription())
def test_cancel_error_in_cancel(self, product_retrieve_mock, subscription_delete_mock): subscription_delete_mock.side_effect = InvalidRequestError("Unexpected error", "blah") subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) with self.assertRaises(InvalidRequestError): subscription.cancel(at_period_end=False) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
def test_update_with_plan_model(self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) new_plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN_II)) self.assertEqual(FAKE_PLAN["id"], subscription.plan.stripe_id) new_subscription = subscription.update(plan=new_plan) self.assertEqual(FAKE_PLAN_II["id"], new_subscription.plan.stripe_id)
def test_str(self, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual( str(subscription), "{email} on {plan}".format(email=self.user.email, plan=str(subscription.plan)), ) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
def test_update_set_empty_value(self, customer_retrieve_mock, subscription_retrieve_mock, plan_retrieve_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription_fake.update({'tax_percent': Decimal(20.0)}) subscription_retrieve_mock.return_value = subscription_fake subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual(Decimal(20.0), subscription.tax_percent) new_subscription = subscription.update(tax_percent=Decimal(0.0)) self.assertEqual(Decimal(0.0), new_subscription.tax_percent)
def test_is_status_temporarily_current_false(self, customer_retrieve_mock, plan_retreive_mock): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) subscription.current_period_end = timezone.now() + timezone.timedelta(days=7) subscription.save() self.assertTrue(subscription.is_status_current()) self.assertFalse(subscription.is_status_temporarily_current()) self.assertTrue(subscription.is_valid()) self.assertTrue(subscription in self.customer.active_subscriptions) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription())
def test_get_subscription(self): """Test a GET to the SubscriptionRestView. Should return the correct data. """ plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN)) subscription = Subscription.sync_from_stripe_data(deepcopy(FAKE_SUBSCRIPTION)) response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["plan"], plan.id) self.assertEqual(response.data['status'], subscription.status) self.assertEqual(response.data['cancel_at_period_end'], subscription.cancel_at_period_end)
def test_user_active_subscription(self, product_retrieve_mock, plan_retrieve_mock): user = get_user_model().objects.create_user( username="******", email="*****@*****.**" ) FAKE_CUSTOMER.create_for_user(user) subscription = Subscription.sync_from_stripe_data(deepcopy(FAKE_SUBSCRIPTION)) subscription.current_period_end = FUTURE_DATE subscription.save() request = self.factory.get("/account/") request.user = user response = self.test_view(request) self.assertEqual(response.status_code, 200)
def test_extend_with_trial(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=5) subscription.save() delta = timezone.timedelta(days=30) new_trial_end = subscription.trial_end + delta extended_subscription = subscription.extend(delta) self.assertEqual(new_trial_end.replace(microsecond=0), extended_subscription.trial_end) self.assertTrue(self.customer.has_active_subscription()) self.assertTrue(self.customer.has_any_active_subscription())
def test_cancel_already_canceled( self, subscription_retrieve_mock, product_retrieve_mock, subscription_delete_mock ): subscription_delete_mock.side_effect = InvalidRequestError( "No such subscription: sub_xxxx", "blah" ) subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual(Subscription.objects.filter(status="canceled").count(), 0) subscription.cancel(at_period_end=False) self.assertEqual(Subscription.objects.filter(status="canceled").count(), 1) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
def setUp(self): self.settings(ROOT_URLCONF=self.urlconf) self.factory = RequestFactory() self.user = get_user_model().objects.create_user( username="******", email="*****@*****.**" ) self.customer = Customer.sync_from_stripe_data(FAKE_CUSTOMER) self.customer.subscriber = self.user self.customer.save() with patch( "stripe.Product.retrieve", return_value=deepcopy(FAKE_PRODUCT), autospec=True ): self.subscription = Subscription.sync_from_stripe_data(FAKE_SUBSCRIPTION) self.middleware = SubscriptionPaymentMiddleware()
def test_update( self, customer_retrieve_mock, subscription_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual(1, subscription.quantity) new_subscription = subscription.update(quantity=4) self.assertEqual(4, new_subscription.quantity) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
def test_is_status_temporarily_current_false_and_cancelled( self, customer_retrieve_mock, product_retrieve_mock, plan_retrieve_mock ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription = Subscription.sync_from_stripe_data(subscription_fake) subscription.status = SubscriptionStatus.canceled subscription.current_period_end = timezone.now() + timezone.timedelta(days=7) subscription.save() self.assertFalse(subscription.is_status_current()) self.assertFalse(subscription.is_status_temporarily_current()) self.assertFalse(subscription.is_valid()) self.assertFalse(subscription in self.customer.active_subscriptions) self.assertFalse(self.customer.has_active_subscription()) self.assertFalse(self.customer.has_any_active_subscription()) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})
def test_get_subscription(self): """Test a GET to the SubscriptionRestView. Should return the correct data. """ with patch( "stripe.Product.retrieve", return_value=deepcopy(FAKE_PRODUCT), autospec=True ): plan = Plan.sync_from_stripe_data(deepcopy(FAKE_PLAN)) subscription = Subscription.sync_from_stripe_data(deepcopy(FAKE_SUBSCRIPTION)) response = self.client.get(self.url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["plan"], plan.djstripe_id) self.assertEqual(response.data["status"], subscription.status) self.assertEqual( response.data["cancel_at_period_end"], subscription.cancel_at_period_end )
def test_update_set_empty_value( self, customer_retrieve_mock, subscription_retrieve_mock, product_retrieve_mock, plan_retrieve_mock, ): subscription_fake = deepcopy(FAKE_SUBSCRIPTION) subscription_fake.update({"tax_percent": Decimal(20.0)}) subscription_retrieve_mock.return_value = subscription_fake subscription = Subscription.sync_from_stripe_data(subscription_fake) self.assertEqual(Decimal(20.0), subscription.tax_percent) new_subscription = subscription.update(tax_percent=Decimal(0.0)) self.assertEqual(Decimal(0.0), new_subscription.tax_percent) self.assert_fks(subscription, expected_blank_fks={"djstripe.Customer.coupon"})