Skip to content

Commit

Permalink
feat: Add field to allow auto-apply without SSO
Browse files Browse the repository at this point in the history
  • Loading branch information
brobro10000 committed Oct 4, 2024
1 parent dcfdbf4 commit e98faef
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 8 deletions.
1 change: 1 addition & 0 deletions license_manager/apps/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ class Meta:
'expired_subscription_modal_messaging',
'hyper_link_text_for_expired_modal',
'url_for_expired_modal',
'enable_auto_applied_subscriptions_with_universal_link'
]

def get_subscription_for_auto_applied_licenses(self, obj):
Expand Down
1 change: 1 addition & 0 deletions license_manager/apps/subscriptions/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ class CustomerAgreementAdmin(admin.ModelAdmin):
'expired_subscription_modal_messaging',
'hyper_link_text_for_expired_modal',
'url_for_expired_modal',
'enable_auto_applied_subscriptions_with_universal_link'
)
custom_fields = ('subscription_for_auto_applied_licenses',)

Expand Down
8 changes: 8 additions & 0 deletions license_manager/apps/subscriptions/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ class LicenseTypesToRenew:
)


class SubscriptionPlanShouldAutoApplyLicensesChoices:
CHOICES = (
(None, "----------"),
(True, "Yes"),
(False, "No")
)


class SubscriptionPlanChangeReasonChoices:
NONE = None
NEW = "new"
Expand Down
15 changes: 12 additions & 3 deletions license_manager/apps/subscriptions/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
MAX_NUM_LICENSES,
MIN_NUM_LICENSES,
SubscriptionPlanChangeReasonChoices,
SubscriptionPlanShouldAutoApplyLicensesChoices,
)
from license_manager.apps.subscriptions.models import (
CustomerAgreement,
Expand All @@ -40,6 +41,14 @@ class SubscriptionPlanForm(forms.ModelForm):
"""
Form used for the SubscriptionPlan admin class.
"""

should_auto_apply_licenses = forms.ChoiceField(
choices=SubscriptionPlanShouldAutoApplyLicensesChoices.CHOICES,
required=False,
label="Should auto apply licenses",
help_text="Whether licenses from this Subscription Plan should be auto applied."
)

# Extra form field to specify the number of licenses to be associated with the subscription plan
num_licenses = forms.IntegerField(
label="Number of Licenses",
Expand Down Expand Up @@ -276,15 +285,15 @@ def populate_subscription_for_auto_applied_licenses_choices(self, instance):
start_date__lte=now,
expiration_date__gte=now
)

current_plan = instance.auto_applicable_subscription

empty_choice = ('', '------')
choices = [empty_choice] + [(plan.uuid, plan.title) for plan in active_plans]
choice_field = forms.ChoiceField(
choices=choices,
required=False,
initial=empty_choice if not current_plan else (current_plan.uuid, current_plan.title)
initial=empty_choice if not current_plan else (current_plan.uuid, current_plan.title),
help_text="The subscription plan with auto applied licences enabled. If you do not see the subscription in "
"the dropdown, please enable \"Should auto apply licenses\" from the subscription plan admin page."
)
self.fields['subscription_for_auto_applied_licenses'] = choice_field

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.2.16 on 2024-10-02 20:49

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('subscriptions', '0070_customeragreement_expired_subscription_modal_messaging_and_more'),
]

operations = [
migrations.AddField(
model_name='customeragreement',
name='enable_auto_applied_subscriptions_with_universal_link',
field=models.BooleanField(default=False, help_text='By default, auto-applied subscriptions are only granted when learners join thier enterprise via SSO Checking this box will enable subscription licenses to be applied when a learner joins the enterprise via Universal link as well'),
),
migrations.AddField(
model_name='historicalcustomeragreement',
name='enable_auto_applied_subscriptions_with_universal_link',
field=models.BooleanField(default=False, help_text='By default, auto-applied subscriptions are only granted when learners join thier enterprise via SSO Checking this box will enable subscription licenses to be applied when a learner joins the enterprise via Universal link as well'),
),
]
11 changes: 11 additions & 0 deletions license_manager/apps/subscriptions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,15 @@ class CustomerAgreement(TimeStampedModel):
)
)

enable_auto_applied_subscriptions_with_universal_link = models.BooleanField(
default=False,
help_text=_(
"By default, auto-applied subscriptions are only granted when learners join thier enterprise via SSO "
"Checking this box will enable subscription licenses to be applied when a learner joins the enterprise via "
"Universal link as well"
)
)

history = HistoricalRecords()

@property
Expand Down Expand Up @@ -596,6 +605,7 @@ def num_revocations_remaining(self):

num_revocations_allowed = ceil(self.num_licenses * (self.revoke_max_percentage / 100))
return num_revocations_allowed - self.num_revocations_applied

num_revocations_remaining.fget.short_description = "Number of Revocations Remaining"

@property
Expand Down Expand Up @@ -1036,6 +1046,7 @@ class License(TimeStampedModel):
.. pii_types: id,email_address
.. pii_retirement: local_api
"""

class Meta:
indexes = [
models.Index(fields=["subscription_plan", "status"], name="subscription_plan_status_idx"),
Expand Down
1 change: 1 addition & 0 deletions license_manager/apps/subscriptions/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Meta:
default_enterprise_catalog_uuid = factory.LazyFunction(uuid4)
enterprise_customer_name = factory.LazyAttribute(lambda x: FAKER.company())
disable_onboarding_notifications = False
enable_auto_applied_subscriptions_with_universal_link = False


class PlanTypeFactory(factory.django.DjangoModelFactory):
Expand Down
5 changes: 4 additions & 1 deletion license_manager/apps/subscriptions/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ def test_select_subscription_for_auto_applied_licenses(mock_toggle_auto_apply_li
request = RequestFactory()
request.user = UserFactory()
customer_agreement = CustomerAgreementFactory()
subscription_plan = SubscriptionPlanFactory(customer_agreement=customer_agreement)
subscription_plan = SubscriptionPlanFactory(
customer_agreement=customer_agreement,
)

customer_agreement_uuid = str(customer_agreement.uuid)
subscription_uuid = str(subscription_plan.uuid)
request.resolver_match = mock.Mock(kwargs={'object_id': customer_agreement_uuid})
Expand Down
5 changes: 3 additions & 2 deletions license_manager/apps/subscriptions/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,15 +236,16 @@ def test_populate_subscription_for_auto_applied_licenses_choices(self):

form = make_bound_customer_agreement_form(
customer_agreement=customer_agreement,
subscription_for_auto_applied_licenses=None
subscription_for_auto_applied_licenses=''
)

field = form.fields['subscription_for_auto_applied_licenses']
choices = field.choices
initial = field.initial
self.assertEqual(len(choices), 2)
self.assertEqual(choices[0], ('', '------'))
self.assertEqual(choices[1], (active_subscription_plan.uuid, active_subscription_plan.title))
self.assertEqual(field.initial, ('', '------'))
self.assertEqual(initial, ('', '------'))

def test_populate_subscription_for_auto_applied_licenses_choices_initial_choice(self):
customer_agreement = CustomerAgreementFactory()
Expand Down
4 changes: 2 additions & 2 deletions pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
# SERIOUSLY.
#
# ------------------------------
# Generated by edx-lint version: 5.3.6
# Generated by edx-lint version: 5.4.0
# ------------------------------
[MASTER]
ignore = ,migrations, settings, wsgi.py
Expand Down Expand Up @@ -401,4 +401,4 @@ int-import-graph =
[EXCEPTIONS]
overgeneral-exceptions = builtins.Exception

# fe60e0fc0935adda7e448a1daaa3ef3547352d92
# ea586deca5871e992466c748232382f9dfadff18

0 comments on commit e98faef

Please sign in to comment.