Skip to content

Commit

Permalink
fix: serializer no longer crashes on bad data
Browse files Browse the repository at this point in the history
This protection against crashing is nice because we use the serializer
in django admin, so bad data also crashes django admin.
  • Loading branch information
pwnage101 committed Oct 24, 2023
1 parent b51b299 commit 1567121
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
43 changes: 38 additions & 5 deletions enterprise_access/apps/api/serializers/subsidy_access_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.",
Expand All @@ -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):
Expand All @@ -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):
Expand Down
9 changes: 9 additions & 0 deletions enterprise_access/apps/subsidy_access_policy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 1567121

Please sign in to comment.