From 160db2c6e410fc5a788b684b4b5a8fb9c5023745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20Hol=C3=BD?= Date: Tue, 2 Apr 2024 14:27:38 +0200 Subject: [PATCH] migrate to RecurringUserPlan.renewal_triggered_by --- HISTORY.rst | 8 ++ plans_payments/models.py | 39 +++++++- requirements.txt | 2 +- setup.py | 2 +- tests/test_models.py | 188 ++++++++++++++++++++++++++++++++++++--- 5 files changed, 220 insertions(+), 19 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 64e20fe..56625f2 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,6 +3,14 @@ History ------- +1.4.0 (2024-04-15) +++++++++++++++++++ + +* migrate to `RecurringUserPlan.renewal_triggered_by` +* add `renewal_triggered_by` parameter to `Payment.set_renew_token` +* deprecate `automatic_renewal` parameter of `Payment.set_renew_token`; use `renewal_triggered_by` parameter instead +* deprecate `None` value of `renewal_triggered_by` parameter of `Payment.set_renew_token`; set an `AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY` instead + 1.3.1 (2024-04-15) ++++++++++++++++++ diff --git a/plans_payments/models.py b/plans_payments/models.py index 440c862..599ae57 100644 --- a/plans_payments/models.py +++ b/plans_payments/models.py @@ -1,5 +1,6 @@ import json import logging +import warnings from decimal import Decimal from urllib.parse import urljoin @@ -12,6 +13,7 @@ from payments.core import get_base_url from payments.models import BasePayment from payments.signals import status_changed +from plans.base.models import AbstractRecurringUserPlan from plans.contrib import get_user_language, send_template_email from plans.models import Order from plans.signals import account_automatic_renewal @@ -125,13 +127,43 @@ def set_renew_token( card_expire_year=None, card_expire_month=None, card_masked_number=None, - automatic_renewal=True, + # TODO: automatic_renewal deprecated. Remove in the next major release. + automatic_renewal=None, + # TODO: renewal_triggered_by=None deprecated. Set to TASK in the next major release. + renewal_triggered_by=None, ): """ Store the recurring payments renew token for user of this payment The renew token is string defined by the provider Used by PayU provider for now """ + if automatic_renewal is None and renewal_triggered_by is None: + automatic_renewal = True + if automatic_renewal is not None: + warnings.warn( + "automatic_renewal is deprecated. Use renewal_triggered_by instead.", + DeprecationWarning, + ) + if renewal_triggered_by == "user": + renewal_triggered_by = AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY.USER + elif renewal_triggered_by == "task": + renewal_triggered_by = AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY.TASK + elif renewal_triggered_by == "other": + renewal_triggered_by = AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY.OTHER + elif renewal_triggered_by is None: + warnings.warn( + "renewal_triggered_by=None is deprecated. " + "Set an AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY instead.", + DeprecationWarning, + ) + renewal_triggered_by = ( + AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY.TASK + if automatic_renewal + else AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY.USER + ) + else: + raise ValueError(f"Invalid renewal_triggered_by: {renewal_triggered_by}") + self.order.user.userplan.set_plan_renewal( order=self.order, token=token, @@ -139,7 +171,7 @@ def set_renew_token( card_expire_year=card_expire_year, card_expire_month=card_expire_month, card_masked_number=card_masked_number, - has_automatic_renewal=automatic_renewal, + renewal_triggered_by=renewal_triggered_by, ) @@ -181,7 +213,8 @@ def renew_accounts(sender, user, *args, **kwargs): userplan = user.userplan if ( userplan.recurring.payment_provider in settings.PAYMENT_VARIANTS - and userplan.recurring.has_automatic_renewal + and userplan.recurring.renewal_triggered_by + == AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY.TASK ): order = userplan.recurring.create_renew_order() diff --git a/requirements.txt b/requirements.txt index f648527..96cbf0d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Additional requirements go here -django-plans>=1.0.7 +django-plans>=1.1.0 django-payments django-related-admin diff --git a/setup.py b/setup.py index f3a0b8f..140380d 100755 --- a/setup.py +++ b/setup.py @@ -57,7 +57,7 @@ def get_version(*file_paths): ], include_package_data=True, install_requires=[ - "django-plans>=1.0.7", + "django-plans>=1.1.0", "django-payments", ], license="MIT", diff --git a/tests/test_models.py b/tests/test_models.py index f2f8c00..83c3100 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -8,6 +8,7 @@ Tests for `django-plans-payments` models module. """ import json +import warnings from datetime import datetime from decimal import Decimal @@ -16,7 +17,7 @@ from freezegun import freeze_time from model_bakery import baker from payments import PaymentStatus -from plans.models import Invoice, Order +from plans.models import Invoice, Order, RecurringUserPlan from plans_payments import models @@ -187,22 +188,140 @@ def test_get_renew_token_verified(self): ) self.assertEqual(p.get_renew_token(), "token") - def test_set_renew_token(self): + def test_set_renew_token_task(self): user = baker.make("User") p = models.Payment(order=baker.make("Order", user=user)) userplan = baker.make("UserPlan", user=user) - p.set_renew_token( - "token", - card_expire_year=2020, - card_expire_month=12, - card_masked_number="1234", - automatic_renewal=True, + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + p.set_renew_token( + "token", + card_expire_year=2020, + card_expire_month=12, + card_masked_number="1234", + renewal_triggered_by="task", + ) + self.assertEqual(userplan.recurring.token, "token") + self.assertEqual(userplan.recurring.card_expire_year, 2020) + self.assertEqual(userplan.recurring.card_expire_month, 12) + self.assertEqual(userplan.recurring.card_masked_number, "1234") + self.assertEqual( + userplan.recurring.renewal_triggered_by, + RecurringUserPlan.RENEWAL_TRIGGERED_BY.TASK, + ) + self.assertFalse(caught_warnings) + + def test_set_renew_token_other(self): + user = baker.make("User") + p = models.Payment(order=baker.make("Order", user=user)) + userplan = baker.make("UserPlan", user=user) + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + p.set_renew_token( + "token", + card_expire_year=2020, + card_expire_month=12, + card_masked_number="1234", + renewal_triggered_by="other", + ) + self.assertEqual(userplan.recurring.token, "token") + self.assertEqual(userplan.recurring.card_expire_year, 2020) + self.assertEqual(userplan.recurring.card_expire_month, 12) + self.assertEqual(userplan.recurring.card_masked_number, "1234") + self.assertEqual( + userplan.recurring.renewal_triggered_by, + RecurringUserPlan.RENEWAL_TRIGGERED_BY.OTHER, + ) + self.assertFalse(caught_warnings) + + def test_set_renew_token_user(self): + user = baker.make("User") + p = models.Payment(order=baker.make("Order", user=user)) + userplan = baker.make("UserPlan", user=user) + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + p.set_renew_token( + "token", + card_expire_year=2020, + card_expire_month=12, + card_masked_number="1234", + renewal_triggered_by="user", + ) + self.assertEqual(userplan.recurring.token, "token") + self.assertEqual(userplan.recurring.card_expire_year, 2020) + self.assertEqual(userplan.recurring.card_expire_month, 12) + self.assertEqual(userplan.recurring.card_masked_number, "1234") + self.assertEqual( + userplan.recurring.renewal_triggered_by, + RecurringUserPlan.RENEWAL_TRIGGERED_BY.USER, + ) + self.assertFalse(caught_warnings) + + def test_set_renew_token_none_automatic_renewal_true(self): + user = baker.make("User") + p = models.Payment(order=baker.make("Order", user=user)) + userplan = baker.make("UserPlan", user=user) + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + p.set_renew_token( + "token", + card_expire_year=2020, + card_expire_month=12, + card_masked_number="1234", + automatic_renewal=True, + ) + self.assertEqual(userplan.recurring.token, "token") + self.assertEqual(userplan.recurring.card_expire_year, 2020) + self.assertEqual(userplan.recurring.card_expire_month, 12) + self.assertEqual(userplan.recurring.card_masked_number, "1234") + self.assertEqual( + userplan.recurring.renewal_triggered_by, + RecurringUserPlan.RENEWAL_TRIGGERED_BY.TASK, ) + self.assertEqual(len(caught_warnings), 2) + self.assertTrue(issubclass(caught_warnings[0].category, DeprecationWarning)) + self.assertEqual( + str(caught_warnings[0].message), + "automatic_renewal is deprecated. Use renewal_triggered_by instead.", + ) + self.assertTrue(issubclass(caught_warnings[1].category, DeprecationWarning)) + self.assertEqual( + str(caught_warnings[1].message), + "renewal_triggered_by=None is deprecated. Set an AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY instead.", + ) + + def test_set_renew_token_none_automatic_renewal_false(self): + user = baker.make("User") + p = models.Payment(order=baker.make("Order", user=user)) + userplan = baker.make("UserPlan", user=user) + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + p.set_renew_token( + "token", + card_expire_year=2020, + card_expire_month=12, + card_masked_number="1234", + automatic_renewal=False, + ) self.assertEqual(userplan.recurring.token, "token") self.assertEqual(userplan.recurring.card_expire_year, 2020) self.assertEqual(userplan.recurring.card_expire_month, 12) self.assertEqual(userplan.recurring.card_masked_number, "1234") - self.assertEqual(userplan.recurring.has_automatic_renewal, True) + self.assertEqual( + userplan.recurring.renewal_triggered_by, + RecurringUserPlan.RENEWAL_TRIGGERED_BY.USER, + ) + self.assertEqual(len(caught_warnings), 2) + self.assertTrue(issubclass(caught_warnings[0].category, DeprecationWarning)) + self.assertEqual( + str(caught_warnings[0].message), + "automatic_renewal is deprecated. Use renewal_triggered_by instead.", + ) + self.assertTrue(issubclass(caught_warnings[1].category, DeprecationWarning)) + self.assertEqual( + str(caught_warnings[1].message), + "renewal_triggered_by=None is deprecated. Set an AbstractRecurringUserPlan.RENEWAL_TRIGGERED_BY instead.", + ) def test_change_payment_status(self): p = models.Payment(order=baker.make("Order", status=Order.STATUS.NEW)) @@ -351,13 +470,15 @@ def test_renew_accounts_no_variant(self): baker.make( "RecurringUserPlan", user_plan=userplan, - renewal_trigger=RecurringUserPlan.RENEWAL_TRIGGER.TASK, - has_automatic_renewal=True, + renewal_triggered_by=RecurringUserPlan.RENEWAL_TRIGGERED_BY.TASK, ) - models.renew_accounts("sender", user, p) + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + models.renew_accounts("sender", user, p) self.assertEqual(p.autorenewed_payment, False) self.assertFalse(Order.objects.exists()) self.assertFalse(models.Payment.objects.exclude(id=p.id).exists()) + self.assertFalse(caught_warnings) def test_renew_accounts(self): p = baker.make("Payment", variant="default", order__amount=12) @@ -369,11 +490,13 @@ def test_renew_accounts(self): "RecurringUserPlan", user_plan=userplan, payment_provider="default", - has_automatic_renewal=True, + renewal_triggered_by=RecurringUserPlan.RENEWAL_TRIGGERED_BY.TASK, amount=14, pricing=plan_pricing.pricing, ) - models.renew_accounts("sender", user, p) + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + models.renew_accounts("sender", user, p) (order_renewed,) = Order.objects.exclude(id=p.order.id) (payment_renewed,) = models.Payment.objects.exclude(id=p.id) self.assertEqual(p.autorenewed_payment, False) @@ -384,6 +507,43 @@ def test_renew_accounts(self): self.assertEqual(payment_renewed.order, order_renewed) self.assertEqual(payment_renewed.variant, "default") self.assertTrue(payment_renewed.autorenewed_payment) + self.assertFalse(caught_warnings) + + def test_renew_accounts_user(self): + p = models.Payment(variant="default") + user = baker.make("User") + userplan = baker.make("UserPlan", user=user) + baker.make( + "RecurringUserPlan", + user_plan=userplan, + payment_provider="default", + renewal_triggered_by=RecurringUserPlan.RENEWAL_TRIGGERED_BY.USER, + ) + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + models.renew_accounts("sender", user, p) + self.assertEqual(p.autorenewed_payment, False) + self.assertFalse(Order.objects.exists()) + self.assertFalse(models.Payment.objects.exclude(id=p.id).exists()) + self.assertFalse(caught_warnings) + + def test_renew_accounts_other(self): + p = models.Payment(variant="default") + user = baker.make("User") + userplan = baker.make("UserPlan", user=user) + baker.make( + "RecurringUserPlan", + user_plan=userplan, + payment_provider="default", + renewal_triggered_by=RecurringUserPlan.RENEWAL_TRIGGERED_BY.OTHER, + ) + with warnings.catch_warnings(record=True) as caught_warnings: + warnings.simplefilter("always") + models.renew_accounts("sender", user, p) + self.assertEqual(p.autorenewed_payment, False) + self.assertFalse(Order.objects.exists()) + self.assertFalse(models.Payment.objects.exclude(id=p.id).exists()) + self.assertFalse(caught_warnings) def test_change_payment_status_called(self): """test that change_payment_status receiver is executed when Payment.change_status is called