Skip to content

Commit

Permalink
Merge pull request #304 from openedx/pwnage101/serializer-less-likely…
Browse files Browse the repository at this point in the history
…-to-crash

fix: serializer no longer crashes on bad data
  • Loading branch information
pwnage101 authored Oct 25, 2023
2 parents b51b299 + a48182b commit 9ad845b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 5 deletions.
47 changes: 42 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,13 @@ 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 as exc:
logger.exception(f"HTTPError from subsidy service: {exc}")
return None

@extend_schema_field(serializers.IntegerField)
def get_amount_allocated_usd_cents(self, policy):
Expand All @@ -86,17 +91,49 @@ 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 as exc:
logger.exception(f"HTTPError from subsidy service: {exc}")
return None

@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 as exc:
logger.exception(f"HTTPError from subsidy service: {exc}")
return None

@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 as exc:
logger.exception(f"HTTPError from subsidy service: {exc}")
return None


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 9ad845b

Please sign in to comment.