diff --git a/enterprise_access/apps/api/serializers/subsidy_access_policy.py b/enterprise_access/apps/api/serializers/subsidy_access_policy.py index f4458aaef..1b3cbce79 100644 --- a/enterprise_access/apps/api/serializers/subsidy_access_policy.py +++ b/enterprise_access/apps/api/serializers/subsidy_access_policy.py @@ -10,6 +10,7 @@ from drf_spectacular.utils import extend_schema_field from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey +from requests.exceptions import HTTPError from rest_framework import serializers from enterprise_access.apps.subsidy_access_policy.constants import CENTS_PER_DOLLAR, PolicyTypes @@ -64,9 +65,8 @@ class SubsidyAccessPolicyAggregatesSerializer(serializers.Serializer): f"Total amount allocated for policies of type {PolicyTypes.ASSIGNED_LEARNER_CREDIT} (0 otherwise), in USD.", ), ) - spend_available_usd_cents = serializers.IntegerField( + spend_available_usd_cents = serializers.SerializerMethodField( help_text="Total Amount of available spend for policy, in positive USD cents.", - source="spend_available", ) spend_available_usd = serializers.SerializerMethodField( help_text="Total Amount of available spend for policy, in USD.", @@ -76,8 +76,12 @@ class SubsidyAccessPolicyAggregatesSerializer(serializers.Serializer): def get_amount_redeemed_usd_cents(self, policy): """ Make amount a positive number. + Protect against Subsidy API Errors. """ - return policy.total_redeemed * -1 + try: + return policy.total_redeemed * -1 + except HTTPError: + return 0 @extend_schema_field(serializers.IntegerField) def get_amount_allocated_usd_cents(self, policy): @@ -86,17 +90,46 @@ def get_amount_allocated_usd_cents(self, policy): """ return policy.total_allocated * -1 + @extend_schema_field(serializers.IntegerField) + def get_spend_available_usd_cents(self, policy): + """ + Protect against Subsidy API Errors. + """ + try: + return policy.spend_available + except HTTPError: + return 0 + @extend_schema_field(serializers.FloatField) def get_amount_redeemed_usd(self, policy): - return float(policy.total_redeemed * -1) / CENTS_PER_DOLLAR + """ + Make amount a positive number. + Convert cents to dollars. + Protect against Subsidy API Errors. + """ + try: + return float(policy.total_redeemed * -1) / CENTS_PER_DOLLAR + except HTTPError: + return 0 @extend_schema_field(serializers.FloatField) def get_amount_allocated_usd(self, policy): + """ + Make amount a positive number. + Convert cents to dollars. + """ return float(policy.total_allocated * -1) / CENTS_PER_DOLLAR @extend_schema_field(serializers.FloatField) def get_spend_available_usd(self, policy): - return float(policy.spend_available) / CENTS_PER_DOLLAR + """ + Convert cents to dollars. + Protect against Subsidy API Errors. + """ + try: + return float(policy.spend_available) / CENTS_PER_DOLLAR + except HTTPError: + return 0 class SubsidyAccessPolicyResponseSerializer(serializers.ModelSerializer): diff --git a/enterprise_access/apps/subsidy_access_policy/models.py b/enterprise_access/apps/subsidy_access_policy/models.py index 01c10cb21..be4689760 100644 --- a/enterprise_access/apps/subsidy_access_policy/models.py +++ b/enterprise_access/apps/subsidy_access_policy/models.py @@ -336,6 +336,9 @@ def spend_available(self): Returns: int: quantity >= 0 of USD Cents representing the policy-wide spend available. + + Raises: + requests.exceptions.HTTPError if the request to Subsidy API (to fetch aggregates) fails. """ # This is how much available spend the policy limit would allow, ignoring the subsidy balance. if self.spend_limit is not None: @@ -354,6 +357,9 @@ def total_redeemed(self): Returns: int: quantity <= 0 of USD Cents. + + Raises: + requests.exceptions.HTTPError if the request to Subsidy API (to fetch aggregates) fails. """ return self.aggregates_for_policy().get('total_quantity') or 0 @@ -406,6 +412,9 @@ def get_content_price(self, content_key, content_metadata=None): def aggregates_for_policy(self): """ Returns aggregate transaction data for this policy. + + Raises: + requests.exceptions.HTTPError if the request to Subsidy API fails. """ response_payload = self.subsidy_client.list_subsidy_transactions( subsidy_uuid=self.subsidy_uuid,