From 30574c35f8dd5a077968e05d424c6d730e0aca55 Mon Sep 17 00:00:00 2001 From: Alexander Dusenbery Date: Thu, 18 Jul 2024 10:12:06 -0400 Subject: [PATCH] feat: serialize subscription plan is_current field --- license_manager/apps/api/serializers.py | 5 ++++ .../apps/api/v1/tests/test_views.py | 1 + license_manager/apps/subscriptions/models.py | 8 +++++++ .../apps/subscriptions/tests/test_models.py | 23 +++++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/license_manager/apps/api/serializers.py b/license_manager/apps/api/serializers.py index 20d7099f..e7791e06 100644 --- a/license_manager/apps/api/serializers.py +++ b/license_manager/apps/api/serializers.py @@ -48,6 +48,10 @@ class MinimalSubscriptionPlanSerializer(serializers.ModelSerializer): """ Minimal serializer for the `SubscriptionPlan` model. """ + is_current = serializers.BooleanField( + help_text='Indicates whether start_date <= now <= expiration_date.', + read_only=True, + ) class Meta: model = SubscriptionPlan @@ -59,6 +63,7 @@ class Meta: 'enterprise_customer_uuid', 'enterprise_catalog_uuid', 'is_active', + 'is_current', 'is_revocation_cap_enabled', 'days_until_expiration', 'days_until_expiration_including_renewals', diff --git a/license_manager/apps/api/v1/tests/test_views.py b/license_manager/apps/api/v1/tests/test_views.py index 125e2cdd..3e68fe5a 100644 --- a/license_manager/apps/api/v1/tests/test_views.py +++ b/license_manager/apps/api/v1/tests/test_views.py @@ -938,6 +938,7 @@ def test_subscription_plan_create_staff_user_200(api_client, staff_user, boolean "start_date", "title", "uuid", + "is_current", } assert response.json().keys() == expected_fields diff --git a/license_manager/apps/subscriptions/models.py b/license_manager/apps/subscriptions/models.py index 44b05477..933e9aba 100644 --- a/license_manager/apps/subscriptions/models.py +++ b/license_manager/apps/subscriptions/models.py @@ -15,6 +15,7 @@ from django.db.models.signals import post_delete, post_save from django.dispatch import receiver from django.forms import ValidationError +from django.utils import timezone from django.utils.functional import cached_property from django.utils.translation import gettext as _ from edx_rbac.models import UserRole, UserRoleAssignment @@ -491,6 +492,13 @@ def days_until_expiration(self): """ return days_until(self.expiration_date) + @property + def is_current(self): + """ + Returns a boolean indicating whether start_date <= now <= expiration_date. + """ + return self.start_date <= timezone.now() <= self.expiration_date + @property def has_revocations_remaining(self): """ diff --git a/license_manager/apps/subscriptions/tests/test_models.py b/license_manager/apps/subscriptions/tests/test_models.py index cc45c927..fe65ec00 100644 --- a/license_manager/apps/subscriptions/tests/test_models.py +++ b/license_manager/apps/subscriptions/tests/test_models.py @@ -81,6 +81,29 @@ def test_prior_renewals(self): ) self.assertEqual(renewed_subscription_plan_2.prior_renewals, [renewal_1, renewal_2]) + @ddt.data( + {'start_date_delta': timedelta(days=-1), 'end_date_delta': timedelta(days=1), 'expected_current': True}, + {'start_date_delta': timedelta(days=-1), 'end_date_delta': timedelta(days=0), 'expected_current': True}, + {'start_date_delta': timedelta(days=0), 'end_date_delta': timedelta(days=1), 'expected_current': True}, + {'start_date_delta': timedelta(days=0), 'end_date_delta': timedelta(days=0), 'expected_current': True}, + {'start_date_delta': timedelta(days=1), 'end_date_delta': timedelta(days=1), 'expected_current': False}, + {'start_date_delta': timedelta(days=10), 'end_date_delta': timedelta(days=150), 'expected_current': False}, + {'start_date_delta': timedelta(days=-1), 'end_date_delta': timedelta(days=-1), 'expected_current': False}, + {'start_date_delta': timedelta(days=-10), 'end_date_delta': timedelta(days=-5), 'expected_current': False}, + ) + @ddt.unpack + def test_is_current(self, start_date_delta, end_date_delta, expected_current): + today = localized_utcnow() + with freezegun.freeze_time(today): + subscription_plan = SubscriptionPlanFactory.create( + start_date=today + start_date_delta, + expiration_date=today + end_date_delta, + ) + if expected_current: + self.assertTrue(subscription_plan.is_current) + else: + self.assertFalse(subscription_plan.is_current) + @ddt.data(True, False) def test_is_locked_for_renewal_processing(self, is_locked_for_renewal_processing): today = localized_utcnow()