Skip to content

Commit

Permalink
feat: add additional fields to EnterpriseLearnerOfferApiSerializer (o…
Browse files Browse the repository at this point in the history
  • Loading branch information
adamstankiewicz authored May 10, 2023
1 parent b21e122 commit 68482ce
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 20 deletions.
56 changes: 41 additions & 15 deletions ecommerce/extensions/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1137,46 +1137,71 @@ class Meta:

def _serialize_remaining_balance_value(conditional_offer):
"""
Change value into string and return it unless it is None.
Calculate and return remaining balance on the offer.
"""
remaining_balance = calculate_remaining_offer_balance(conditional_offer)
if remaining_balance is not None:
remaining_balance = str(remaining_balance)
return remaining_balance


class EnterpriseLearnerOfferApiSerializer(serializers.BaseSerializer): # pylint: disable=abstract-method
def _serialize_remaining_balance_for_user(conditional_offer, request):
"""
Serializer for EnterpriseOffer learner endpoint.
Determines the remaining balance for the user.
"""
if request and conditional_offer.max_user_discount is not None:
return str(conditional_offer.max_user_discount - sum_user_discounts_for_offer(request.user, conditional_offer))
return None

Uses serializers.BaseSerializer to keep this lightweight.

def _serialize_remaining_applications_value(conditional_offer):
"""
Calculate and return remaining number of applications on the offer.
"""
if conditional_offer.max_global_applications is not None:
return conditional_offer.max_global_applications - conditional_offer.num_applications
return None

def _serialize_remaining_balance_for_user(self, instance):
request = self.context.get('request')

if request and instance.max_user_discount is not None:
return str(instance.max_user_discount - sum_user_discounts_for_offer(request.user, instance))
def _serialize_remaining_applications_for_user(conditional_offer, request):
"""
Determines the remaining number of applications (enrollments) for the user.
"""
if request and conditional_offer.max_user_applications is not None:
return conditional_offer.max_user_applications - conditional_offer.get_num_user_applications(request.user)
return None

return None

class EnterpriseLearnerOfferApiSerializer(serializers.BaseSerializer): # pylint: disable=abstract-method
"""
Serializer for EnterpriseOffer learner endpoint.
Uses serializers.BaseSerializer to keep this lightweight.
"""

def to_representation(self, instance):
representation = OrderedDict()

representation['id'] = instance.id
representation['max_discount'] = instance.max_discount
representation['enterprise_customer_uuid'] = instance.condition.enterprise_customer_uuid
representation['enterprise_catalog_uuid'] = instance.condition.enterprise_customer_catalog_uuid
representation['is_current'] = instance.is_current
representation['status'] = instance.status
representation['start_datetime'] = instance.start_datetime
representation['end_datetime'] = instance.end_datetime
representation['enterprise_catalog_uuid'] = instance.condition.enterprise_customer_catalog_uuid
representation['usage_type'] = get_benefit_type(instance.benefit)
representation['discount_value'] = instance.benefit.value
representation['status'] = instance.status
representation['remaining_balance'] = _serialize_remaining_balance_value(instance)
representation['is_current'] = instance.is_current
representation['max_discount'] = instance.max_discount
representation['max_global_applications'] = instance.max_global_applications
representation['max_user_applications'] = instance.max_user_applications
representation['max_user_discount'] = instance.max_user_discount
representation['num_applications'] = instance.num_applications
representation['remaining_balance_for_user'] = self._serialize_remaining_balance_for_user(instance)
representation['remaining_balance'] = _serialize_remaining_balance_value(instance)
representation['remaining_applications'] = _serialize_remaining_applications_value(instance)
representation['remaining_balance_for_user'] = \
_serialize_remaining_balance_for_user(instance, request=self.context.get('request'))
representation['remaining_applications_for_user'] = \
_serialize_remaining_applications_for_user(instance, request=self.context.get('request'))

return representation

Expand All @@ -1199,6 +1224,7 @@ def to_representation(self, instance):
representation['enterprise_catalog_uuid'] = instance.condition.enterprise_customer_catalog_uuid
representation['display_name'] = generate_offer_display_name(instance)
representation['remaining_balance'] = _serialize_remaining_balance_value(instance)
representation['remaining_applications'] = _serialize_remaining_applications_value(instance)
representation['is_current'] = instance.is_current

return representation
Expand Down
97 changes: 92 additions & 5 deletions ecommerce/extensions/api/v2/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@
class EnterpriseLearnerOfferApiSerializerTests(TestCase):

@ddt.data(
(100, '74.5'),
(None, None)
(100, 25.5, '74.5'),
(None, None, None)
)
@ddt.unpack
@mock.patch('ecommerce.extensions.api.serializers.sum_user_discounts_for_offer')
def test_serialize_remaining_balance_for_user(
self,
max_user_discount,
expected_remaining_balance,
existing_user_spend,
expected_remaining_balance_for_user,
mock_sum_user_discounts_for_offer
):
mock_sum_user_discounts_for_offer.return_value = 25.5
mock_sum_user_discounts_for_offer.return_value = existing_user_spend
enterprise_customer_uuid = str(uuid4())
condition = extended_factories.EnterpriseCustomerConditionFactory(
enterprise_customer_uuid=enterprise_customer_uuid
Expand All @@ -45,4 +46,90 @@ def test_serialize_remaining_balance_for_user(
}
)
data = serializer.to_representation(enterprise_offer)
assert data['remaining_balance_for_user'] == expected_remaining_balance
assert data['remaining_balance_for_user'] == expected_remaining_balance_for_user

@ddt.data(
(5250, '5250'),
(None, None)
)
@ddt.unpack
@mock.patch('ecommerce.extensions.api.serializers.calculate_remaining_offer_balance')
def test_serialize_remaining_balance(
self,
max_discount,
expected_remaining_balance,
mock_calculate_remaining_offer_balance
):
mock_calculate_remaining_offer_balance.return_value = max_discount
enterprise_customer_uuid = str(uuid4())
condition = extended_factories.EnterpriseCustomerConditionFactory(
enterprise_customer_uuid=enterprise_customer_uuid
)
enterprise_offer = extended_factories.EnterpriseOfferFactory.create(
partner=self.partner,
condition=condition,
)
serializer = EnterpriseLearnerOfferApiSerializer(
data=enterprise_offer,
context={
'request': mock.MagicMock(user=UserFactory())
}
)
data = serializer.to_representation(enterprise_offer)
assert data['remaining_balance'] == expected_remaining_balance

@ddt.data(
(1000, 1000),
(None, None)
)
@ddt.unpack
def test_serialize_remaining_applications_for_user(
self,
max_user_applications,
expected_remaining_applications_for_user,
):
enterprise_customer_uuid = str(uuid4())
condition = extended_factories.EnterpriseCustomerConditionFactory(
enterprise_customer_uuid=enterprise_customer_uuid
)
enterprise_offer = extended_factories.EnterpriseOfferFactory.create(
partner=self.partner,
condition=condition,
max_user_applications=max_user_applications,
)
serializer = EnterpriseLearnerOfferApiSerializer(
data=enterprise_offer,
context={
'request': mock.MagicMock(user=UserFactory())
}
)
data = serializer.to_representation(enterprise_offer)
assert data['remaining_applications_for_user'] == expected_remaining_applications_for_user

@ddt.data(
(2, 2),
(None, None)
)
@ddt.unpack
def test_serialize_remaining_applications(
self,
max_global_applications,
expected_remaining_applications,
):
enterprise_customer_uuid = str(uuid4())
condition = extended_factories.EnterpriseCustomerConditionFactory(
enterprise_customer_uuid=enterprise_customer_uuid
)
enterprise_offer = extended_factories.EnterpriseOfferFactory.create(
partner=self.partner,
condition=condition,
max_global_applications=max_global_applications,
)
serializer = EnterpriseLearnerOfferApiSerializer(
data=enterprise_offer,
context={
'request': mock.MagicMock(user=UserFactory())
}
)
data = serializer.to_representation(enterprise_offer)
assert data['remaining_applications'] == expected_remaining_applications

0 comments on commit 68482ce

Please sign in to comment.