Skip to content

Commit

Permalink
feat: initialize enterprise metadata in HandlerContext; complete auto…
Browse files Browse the repository at this point in the history
…-apply business logic (#586)
  • Loading branch information
adamstankiewicz authored Nov 15, 2024
1 parent 9732d12 commit c99238a
Show file tree
Hide file tree
Showing 7 changed files with 987 additions and 208 deletions.
74 changes: 69 additions & 5 deletions enterprise_access/apps/api_client/lms_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def all_pages_enterprise_group_members_cache_key(


class LmsApiClient(BaseOAuthClient):

"""
API client for calls to the LMS service.
"""
Expand All @@ -64,21 +63,32 @@ def enterprise_group_members_endpoint(self, group_uuid):
"learners/",
)

def get_enterprise_customer_data(self, enterprise_customer_uuid):
def get_enterprise_customer_data(self, enterprise_customer_uuid=None, enterprise_customer_slug=None):
"""
Gets the data for an EnterpriseCustomer for the given uuid.
Gets the data for an EnterpriseCustomer for the given uuid or slug.
Arguments:
enterprise_customer_uuid (string): id of the enterprise customer
enterprise_customer_slug (string): slug of the enterprise customer
Returns:
dictionary containing enterprise customer metadata
"""
if enterprise_customer_uuid:
# Returns a dict
endpoint = f'{self.enterprise_customer_endpoint}{enterprise_customer_uuid}/'
elif enterprise_customer_slug:
# Returns a list of dicts
endpoint = f'{self.enterprise_customer_endpoint}?slug={enterprise_customer_slug}'
else:
raise ValueError('Either enterprise_customer_uuid or enterprise_customer_slug is required.')

try:
endpoint = f'{self.enterprise_customer_endpoint}{enterprise_customer_uuid}/'
response = self.client.get(endpoint, timeout=settings.LMS_CLIENT_TIMEOUT)
response.raise_for_status()
return response.json()
payload = response.json()
if results := payload.get('results'):
return results[0]
return payload
except requests.exceptions.HTTPError as exc:
logger.exception(exc)
raise
Expand Down Expand Up @@ -406,13 +416,67 @@ class LmsUserApiClient(BaseUserApiClient):
enterprise_api_base_url = f"{settings.LMS_URL}/enterprise/api/v1/"
enterprise_learner_portal_api_base_url = f"{settings.LMS_URL}/enterprise_learner_portal/api/v1/"

enterprise_learner_endpoint = f"{enterprise_api_base_url}enterprise-learner/"
default_enterprise_enrollment_intentions_learner_status_endpoint = (
f'{enterprise_api_base_url}default-enterprise-enrollment-intentions/learner-status/'
)
enterprise_course_enrollments_endpoint = (
f'{enterprise_learner_portal_api_base_url}enterprise_course_enrollments/'
)

def get_enterprise_customers_for_user(self, username, traverse_pagination=False):
"""
Fetches enterprise learner data for a given username.
Arguments:
username (str): Username of the learner
Returns:
dict: Dictionary representation of the JSON response from the API
"""
query_params = {
'username': username,
}
results = []
initial_response_data = None
current_response = None
next_url = self.enterprise_learner_endpoint
try:
while next_url:
current_response = self.get(
next_url,
params=query_params,
timeout=settings.LMS_CLIENT_TIMEOUT
)
current_response.raise_for_status()
data = current_response.json()

if not initial_response_data:
# Store the initial response data (first page) for later use
initial_response_data = data

# Collect results from the current page
results.extend(data.get('results', []))

# If pagination is enabled, continue with the next page; otherwise, break
next_url = data.get('next') if traverse_pagination else None

consolidated_response = {
**initial_response_data,
'next': None,
'previous': None,
'count': len(results),
'num_pages': 1,
'results': results,
}
return consolidated_response
except requests.exceptions.HTTPError as exc:
logger.exception(
f"Failed to fetch enterprise learner for learner {username}: {exc} "
f"Response content: {current_response.content if current_response else None}"
)
raise

def get_default_enterprise_enrollment_intentions_learner_status(self, enterprise_customer_uuid):
"""
Fetches learner status from the default enterprise enrollment intentions endpoint.
Expand Down
43 changes: 39 additions & 4 deletions enterprise_access/apps/api_client/tests/test_lms_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,48 @@ def test_get_enterprise_admin_users(self, mock_oauth_client, mock_json):
timeout=settings.LMS_CLIENT_TIMEOUT,
)

@ddt.data(
{
'enterprise_uuid': 'some-uuid',
'enterprise_slug': None
},
{
'enterprise_uuid': None,
'enterprise_slug': 'some-slug',
},
{
'enterprise_uuid': 'some-uuid',
'enterprise_slug': 'some-slug',
},
)
@mock.patch('requests.Response.json')
@mock.patch('enterprise_access.apps.api_client.base_oauth.OAuthAPIClient')
def test_get_enterprise_customer_data(self, mock_oauth_client, mock_json):
@ddt.unpack
def test_get_enterprise_customer_data(
self,
mock_oauth_client,
mock_json,
enterprise_uuid,
enterprise_slug,
):
"""
Verify client hits the right URL for entepriseCustomer data.
"""
mock_json.return_value = {
mock_enterprise_customer = {
'uuid': 'some-uuid',
'slug': 'some-test-slug',
}
mock_json.return_value = mock_enterprise_customer
if not enterprise_uuid and enterprise_slug:
mock_json.return_value = {'results': [mock_enterprise_customer]}
mock_oauth_client.return_value.get.return_value = requests.Response()
mock_oauth_client.return_value.get.return_value.status_code = 200

client = LmsApiClient()
customer_data = client.get_enterprise_customer_data('some-uuid')
customer_data = client.get_enterprise_customer_data(
enterprise_customer_uuid=enterprise_uuid,
enterprise_customer_slug=enterprise_slug,
)

assert customer_data['uuid'] == 'some-uuid'
assert customer_data['slug'] == 'some-test-slug'
Expand All @@ -132,8 +159,16 @@ def test_get_enterprise_customer_data(self, mock_oauth_client, mock_json):
'http://edx-platform.example.com/'
'enterprise/api/v1/'
'enterprise-customer/'
'some-uuid/'
f'{enterprise_uuid}/'
)
if not enterprise_uuid and enterprise_slug:
expected_url = (
'http://edx-platform.example.com/'
'enterprise/api/v1/'
'enterprise-customer/'
f'?slug={enterprise_slug}'
)

mock_oauth_client.return_value.get.assert_called_with(
expected_url,
timeout=settings.LMS_CLIENT_TIMEOUT,
Expand Down
Loading

0 comments on commit c99238a

Please sign in to comment.