Skip to content

Commit

Permalink
feat: Adds additional error reasons to SubsidyAccessPolicy
Browse files Browse the repository at this point in the history
  • Loading branch information
brobro10000 committed Jul 24, 2023
1 parent cfde7ed commit 578f52c
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 19 deletions.
20 changes: 18 additions & 2 deletions enterprise_access/apps/api/v1/views/subsidy_access_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@
REASON_LEARNER_MAX_SPEND_REACHED,
REASON_LEARNER_NOT_IN_ENTERPRISE,
REASON_NOT_ENOUGH_VALUE_IN_SUBSIDY,
REASON_POLICY_NOT_ACTIVE,
REASON_POLICY_EXPIRED,
REASON_POLICY_NO_FUNDS,
REASON_POLICY_SPEND_LIMIT_REACHED,
REASON_SUBSIDY_EXPIRED,
MissingSubsidyAccessReasonUserMessages,
TransactionStateChoices
)
Expand Down Expand Up @@ -503,8 +505,22 @@ def _get_user_message_for_reason(self, reason_slug, enterprise_admin_users):
else MissingSubsidyAccessReasonUserMessages.ORGANIZATION_NO_FUNDS_NO_ADMINS
)

user_message_organization_fund_expired = (
MissingSubsidyAccessReasonUserMessages.ORGANIZATION_EXPIRED_FUNDS
if has_enterprise_admin_users
else MissingSubsidyAccessReasonUserMessages.ORGANIZATION_EXPIRED_FUNDS_NO_ADMINS
)

user_message_organization_plan_expired = (
MissingSubsidyAccessReasonUserMessages.ORGANIZATION_EXPIRED_PLAN
if has_enterprise_admin_users
else MissingSubsidyAccessReasonUserMessages.ORGANIZATION_EXPIRED_PLAN_NO_ADMINS
)

MISSING_SUBSIDY_ACCESS_POLICY_REASONS = {
REASON_POLICY_NOT_ACTIVE: user_message_organization_no_funds,
REASON_POLICY_NO_FUNDS: user_message_organization_no_funds,
REASON_POLICY_EXPIRED: user_message_organization_fund_expired,
REASON_SUBSIDY_EXPIRED: user_message_organization_plan_expired,
REASON_NOT_ENOUGH_VALUE_IN_SUBSIDY: user_message_organization_no_funds,
REASON_POLICY_SPEND_LIMIT_REACHED: user_message_organization_no_funds,
REASON_LEARNER_NOT_IN_ENTERPRISE: MissingSubsidyAccessReasonUserMessages.LEARNER_NOT_IN_ENTERPRISE,
Expand Down
10 changes: 9 additions & 1 deletion enterprise_access/apps/subsidy_access_policy/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,22 @@ class MissingSubsidyAccessReasonUserMessages:
ORGANIZATION_NO_FUNDS_NO_ADMINS = \
"You can't enroll right now because your organization doesn't have enough funds. " \
"Contact your administrator to request more."
ORGANIZATION_EXPIRED_FUNDS = "You can't enroll right now because your funds expired."
ORGANIZATION_EXPIRED_FUNDS_NO_ADMINS = "You can't enroll right now because your funds expired. " \
"Contact your administrator for help."
ORGANIZATION_EXPIRED_PLAN = "You can't enroll right now because your plan expired."
ORGANIZATION_EXPIRED_PLAN_NO_ADMINS = "You can't enroll right now because your plan expired. " \
"Contact your administrator for help."
LEARNER_LIMITS_REACHED = "You can't enroll right now because of limits set by your organization."
CONTENT_NOT_IN_CATALOG = \
"You can't enroll right now because this course is no longer available in your organization's catalog."
LEARNER_NOT_IN_ENTERPRISE = \
"You can't enroll right now because your account is no longer associated with the organization."


REASON_POLICY_NOT_ACTIVE = "policy_not_active"
REASON_POLICY_NO_FUNDS = "policy_not_active"
REASON_POLICY_EXPIRED = "policy_expired"
REASON_SUBSIDY_EXPIRED = "subsidy_expired"
REASON_CONTENT_NOT_IN_CATALOG = "content_not_in_catalog"
REASON_LEARNER_NOT_IN_ENTERPRISE = "learner_not_in_enterprise"
REASON_NOT_ENOUGH_VALUE_IN_SUBSIDY = "not_enough_value_in_subsidy"
Expand Down
45 changes: 32 additions & 13 deletions enterprise_access/apps/subsidy_access_policy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
REASON_LEARNER_MAX_SPEND_REACHED,
REASON_LEARNER_NOT_IN_ENTERPRISE,
REASON_NOT_ENOUGH_VALUE_IN_SUBSIDY,
REASON_POLICY_NOT_ACTIVE,
REASON_POLICY_EXPIRED,
REASON_POLICY_NO_FUNDS,
REASON_POLICY_SPEND_LIMIT_REACHED,
REASON_SUBSIDY_EXPIRED,
AccessMethods,
TransactionStateChoices
)
Expand Down Expand Up @@ -311,6 +313,7 @@ def will_exceed_spend_limit(self, content_key, content_metadata=None):

content_price = self.get_content_price(content_key, content_metadata=content_metadata)
spent_amount = self.aggregates_for_policy().get('total_quantity') or 0

return self.content_would_exceed_limit(spent_amount, self.spend_limit, content_price)

def can_redeem(self, lms_user_id, content_key, skip_customer_user_check=False):
Expand All @@ -321,32 +324,48 @@ def can_redeem(self, lms_user_id, content_key, skip_customer_user_check=False):
3-tuple of (bool, str, list of dict):
* first element is true if the learner can redeem the content,
* second element contains a reason code if the content is not redeemable,
* third a list of any transactions represending existing redemptions (any state).
* third a list of any transactions representing existing redemptions (any state).
"""
content_metadata = self.get_content_metadata(content_key)
subsidy_can_redeem_payload = self.subsidy_client.can_redeem(
self.subsidy_uuid,
lms_user_id,
content_key,
)

active_subsidy = subsidy_can_redeem_payload.get('active', False)
existing_transactions = subsidy_can_redeem_payload.get('all_transactions', [])

# inactive subsidy
if not active_subsidy:
return (False, REASON_SUBSIDY_EXPIRED, [])

# inactive policy with spend remaining (could have redeemed)
if not self.active and not self.will_exceed_spend_limit(content_key, content_metadata=content_metadata):
return (False, REASON_POLICY_NO_FUNDS, [])

# inactive policy
if not self.active:
return (False, REASON_POLICY_NOT_ACTIVE, [])
return (False, REASON_POLICY_EXPIRED, [])

# learner not in enterprise
if not skip_customer_user_check:
if not self.lms_api_client.enterprise_contains_learner(self.enterprise_customer_uuid, lms_user_id):
return (False, REASON_LEARNER_NOT_IN_ENTERPRISE, [])

# no content key not in catalog
if not self.catalog_contains_content_key(content_key):
return (False, REASON_CONTENT_NOT_IN_CATALOG, [])

subsidy_can_redeem_payload = self.subsidy_client.can_redeem(
self.subsidy_uuid,
lms_user_id,
content_key,
)
existing_transactions = subsidy_can_redeem_payload.get('all_transactions', [])
# no content key in content metadata
if not content_metadata:
return (False, REASON_CONTENT_NOT_IN_CATALOG, existing_transactions)

# cannot redeem
if not subsidy_can_redeem_payload.get('can_redeem', False):
return (False, REASON_NOT_ENOUGH_VALUE_IN_SUBSIDY, existing_transactions)

content_metadata = self.get_content_metadata(content_key)
if not content_metadata:
return (False, REASON_CONTENT_NOT_IN_CATALOG, existing_transactions)

# not enough funds
if self.will_exceed_spend_limit(content_key, content_metadata=content_metadata):
return (False, REASON_POLICY_SPEND_LIMIT_REACHED, existing_transactions)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
REASON_LEARNER_MAX_SPEND_REACHED,
REASON_LEARNER_NOT_IN_ENTERPRISE,
REASON_NOT_ENOUGH_VALUE_IN_SUBSIDY,
REASON_POLICY_NOT_ACTIVE,
REASON_POLICY_NO_FUNDS,
REASON_POLICY_SPEND_LIMIT_REACHED
)
from enterprise_access.apps.subsidy_access_policy.models import (
Expand Down Expand Up @@ -246,7 +246,7 @@ def test_object_creation_with_policy_type_in_kwarg(self, *args):
'subsidy_is_redeemable': {'can_redeem': True},
'transactions_for_learner': {'transactions': [], 'aggregates': {}},
'transactions_for_policy': {'results': [], 'aggregates': {'total_quantity': -200}},
'expected_policy_can_redeem': (False, REASON_POLICY_NOT_ACTIVE, []),
'expected_policy_can_redeem': (False, REASON_POLICY_NO_FUNDS, []),
},
)
@ddt.unpack
Expand Down Expand Up @@ -375,7 +375,7 @@ def test_learner_enrollment_cap_policy_can_redeem(
'subsidy_is_redeemable': {'can_redeem': True},
'transactions_for_learner': {'transactions': [], 'aggregates': {}},
'transactions_for_policy': {'results': [], 'aggregates': {'total_quantity': -200}},
'expected_policy_can_redeem': (False, REASON_POLICY_NOT_ACTIVE, []),
'expected_policy_can_redeem': (False, REASON_POLICY_NO_FUNDS, []),
},
)
@ddt.unpack
Expand Down

0 comments on commit 578f52c

Please sign in to comment.