edx-enterprise-data 9.2.1__py3-none-any.whl → 9.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edx-enterprise-data
3
- Version: 9.2.1
3
+ Version: 9.3.0
4
4
  Summary: Enterprise Reporting
5
5
  Home-page: https://github.com/openedx/edx-enterprise-data
6
6
  Author: edX
@@ -1,4 +1,4 @@
1
- enterprise_data/__init__.py,sha256=KS1OhKyx-0mFThb9u4NNxgV6czgcEVQvwYjdMMkap5Y,123
1
+ enterprise_data/__init__.py,sha256=TphLVa4NU_aZY7wDzp1BWmsdL-hb6Y1JbCBQwakIAxU,123
2
2
  enterprise_data/apps.py,sha256=aF6hZwDfI2oWj95tUTm_2ikHueQj-jLj-u0GrgzpsQI,414
3
3
  enterprise_data/clients.py,sha256=GvQupy5TVYfO_IKC3yzXSAgNP54r-PtIjidM5ws9Iks,3947
4
4
  enterprise_data/constants.py,sha256=uCKjfpdlMYFZJsAj3n9RMw4Cmg5_6s3NuwocO-fch3s,238
@@ -15,12 +15,12 @@ enterprise_data/admin_analytics/data_loaders.py,sha256=NixI-4M3D4MnI279x5hqqTw84
15
15
  enterprise_data/admin_analytics/database/__init__.py,sha256=vNSWKf2VV5xMegN7htJJtxtQEb0ASLC6frE2w0ZpYpE,104
16
16
  enterprise_data/admin_analytics/database/utils.py,sha256=5u-d6ZQW95mF_r4bH8Xdi7DgpYAuDFOG_q0P-bjKXHU,1712
17
17
  enterprise_data/admin_analytics/database/queries/__init__.py,sha256=IC5TLOr_GnydbrVbl2mWhwO3aUbYeHuDmfPTLmwGhZA,218
18
- enterprise_data/admin_analytics/database/queries/fact_engagement_admin_dash.py,sha256=28R1uISsLmMrbvTZXF2bGsVCCOyfQzXY-tMzThDndHo,7809
18
+ enterprise_data/admin_analytics/database/queries/fact_engagement_admin_dash.py,sha256=T6iFTSKwRItNvThFH_IqlgOURSEY9Ol4hda8VpHNdiU,7364
19
19
  enterprise_data/admin_analytics/database/queries/fact_enrollment_admin_dash.py,sha256=brRgmgtzPLsOdt1vYrk_EpoQLm2izmOdBapxAxNkXzA,8420
20
20
  enterprise_data/admin_analytics/database/queries/skills_daily_rollup_admin_dash.py,sha256=PgWwvtVCK5lbiq6z44lH0fwbkdWYukhyXZL9X8lNWCY,4099
21
21
  enterprise_data/admin_analytics/database/tables/__init__.py,sha256=Z-c3P9hqR-dC9uYKe63qHkQG9Nms8cLE2jRN-4jeMM0,289
22
22
  enterprise_data/admin_analytics/database/tables/base.py,sha256=1KyKsC18pW3m-5U-T6pdt5rIwsz6Wp3QFFbD3r6L6YQ,395
23
- enterprise_data/admin_analytics/database/tables/fact_engagement_admin_dash.py,sha256=cA-Y63LQVDD7UHv5rYdX2091R7W6clcT2DXO0VbMhVQ,7354
23
+ enterprise_data/admin_analytics/database/tables/fact_engagement_admin_dash.py,sha256=tEtlgt2CMQeoBexanm3UpV77RYUtD-IzW-LkFZP8iWI,10077
24
24
  enterprise_data/admin_analytics/database/tables/fact_enrollment_admin_dash.py,sha256=q1XB7aDwFzllS5lBQNfS2y7drehqiK7o0J1eiYzqFOk,10854
25
25
  enterprise_data/admin_analytics/database/tables/skills_daily_rollup_admin_dash.py,sha256=9PqLeVqByrz7R0qumRbwJlr5lzIWn7Fl7WEGM0aJVlw,3131
26
26
  enterprise_data/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -39,7 +39,7 @@ enterprise_data/api/v1/views/analytics_enrollments.py,sha256=HXgoFwvXk-CZcf6qbVO
39
39
  enterprise_data/api/v1/views/analytics_leaderboard.py,sha256=zwd-2A2sctjAdx5BUjCqiwcZ5aNvM8wfm386pR-RwGQ,4114
40
40
  enterprise_data/api/v1/views/base.py,sha256=Kkmd5zgEBAhvwS_GoGXSK6lgbDNwSPioYn-QbnizI3w,3416
41
41
  enterprise_data/api/v1/views/enterprise_admin.py,sha256=DsR1oHFhe6LCIFjIJ4YLLZ7PUChvNlFfdZD-sxHoijY,7388
42
- enterprise_data/api/v1/views/enterprise_learner.py,sha256=xy9DwCy2eYLnb0z3XolOstxf9faIPHG2aXUXSuWrodM,19231
42
+ enterprise_data/api/v1/views/enterprise_learner.py,sha256=HemAL1ndJT7crK2_A81o6ozvrNscNxLFPSRm3D0lDbo,18188
43
43
  enterprise_data/api/v1/views/enterprise_offers.py,sha256=VifxgqTLFLVw4extYPlHcN1N_yjXcsYsAlYEnAbpb10,1266
44
44
  enterprise_data/fixtures/enterprise_enrollment.json,sha256=6onPXXR29pMdTdbl_mn81sDi3Re5jkLUZz2TPMB_1IY,5786
45
45
  enterprise_data/fixtures/enterprise_user.json,sha256=6g8GvNY9j_fh1dvAU80bTAMI2F5vXCkb8a4UjsftMvQ,1970
@@ -167,8 +167,8 @@ enterprise_reporting/tests/test_send_enterprise_reports.py,sha256=WtL-RqGgu2x5PP
167
167
  enterprise_reporting/tests/test_utils.py,sha256=Zt_TA0LVb-B6fQGkUkAKKVlUKKnQh8jnw1US1jKe7g8,9493
168
168
  enterprise_reporting/tests/test_vertica_client.py,sha256=-R2yNCGUjRtoXwLMBloVFQkFYrJoo613VCr61gwI3kQ,140
169
169
  enterprise_reporting/tests/utils.py,sha256=xms2LM7DV3wczXEfctOK1ddel1EE0J_YSr17UzbCDy4,1401
170
- edx_enterprise_data-9.2.1.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
171
- edx_enterprise_data-9.2.1.dist-info/METADATA,sha256=ThIreeBfPl0yvMU4JURsx2TnlXEizu5eCi6f38iAr2A,1569
172
- edx_enterprise_data-9.2.1.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
173
- edx_enterprise_data-9.2.1.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
174
- edx_enterprise_data-9.2.1.dist-info/RECORD,,
170
+ edx_enterprise_data-9.3.0.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
171
+ edx_enterprise_data-9.3.0.dist-info/METADATA,sha256=INB7KBDJdZkWf_nFY5UCwZy8D1OizsUjluoi5VxR6po,1569
172
+ edx_enterprise_data-9.3.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
173
+ edx_enterprise_data-9.3.0.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
174
+ edx_enterprise_data-9.3.0.dist-info/RECORD,,
@@ -2,4 +2,4 @@
2
2
  Enterprise data api application. This Django app exposes API endpoints used by enterprises.
3
3
  """
4
4
 
5
- __version__ = "9.2.1"
5
+ __version__ = "9.3.0"
@@ -111,59 +111,62 @@ class FactEngagementAdminDashQueries:
111
111
  """
112
112
 
113
113
  @staticmethod
114
- def get_all_leaderboard_data_query():
114
+ def get_engagement_data_for_leaderboard_query():
115
115
  """
116
- Get the query to fetch the leaderboard data.
116
+ Get the query to fetch the engagement data for leaderboard.
117
117
 
118
- Query should fetch the leaderboard data for the enterprise customer to show in the data table.
118
+ Query should fetch the engagement data for like learning time, session length of
119
+ the enterprise learners to show in the leaderboard.
119
120
 
120
121
  Returns:
121
- (str): Query to fetch the leaderboard data.
122
+ (str): Query to fetch the engagement data for leaderboard.
122
123
  """
123
124
  return """
124
- WITH Engagement AS (
125
- SELECT
126
- email,
127
- ROUND(SUM(learning_time_seconds) / 3600, 1) as learning_time_hours,
128
- SUM(is_engaged) as session_count,
129
- CASE
130
- WHEN SUM(is_engaged) = 0 THEN 0.0
131
- ELSE ROUND(SUM(learning_time_seconds) / 3600 / SUM(is_engaged), 1)
132
- END AS average_session_length
133
- FROM fact_enrollment_engagement_day_admin_dash
134
- WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
135
- (activity_date BETWEEN %(start_date)s AND %(end_date)s) AND
136
- is_engaged = 1
137
- GROUP BY email
138
- ),
139
- Completions AS (
140
- SELECT email, count(course_key) as course_completion_count
141
- FROM fact_enrollment_admin_dash
142
- WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
143
- (passed_date BETWEEN %(start_date)s AND %(end_date)s) AND
144
- has_passed = 1
145
- GROUP BY email
146
- )
147
125
  SELECT
148
- Engagement.email,
149
- Engagement.learning_time_hours,
150
- Engagement.session_count,
151
- Engagement.average_session_length,
152
- Completions.course_completion_count
153
- FROM Engagement
154
- LEFT JOIN Completions
155
- ON Engagement.email = Completions.email
156
- ORDER BY
157
- Engagement.learning_time_hours DESC,
158
- Engagement.session_count DESC,
159
- Completions.course_completion_count DESC
126
+ email,
127
+ ROUND(SUM(learning_time_seconds) / 3600, 1) as learning_time_hours,
128
+ SUM(is_engaged) as session_count,
129
+ CASE
130
+ WHEN SUM(is_engaged) = 0 THEN 0.0
131
+ ELSE ROUND(SUM(learning_time_seconds) / 3600 / SUM(is_engaged), 1)
132
+ END AS average_session_length
133
+ FROM fact_enrollment_engagement_day_admin_dash
134
+ WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
135
+ (activity_date BETWEEN %(start_date)s AND %(end_date)s) AND
136
+ is_engaged = 1
137
+ GROUP BY email
138
+ ORDER BY learning_time_hours DESC
160
139
  LIMIT %(limit)s OFFSET %(offset)s;
161
140
  """
162
141
 
142
+ @staticmethod
143
+ def get_completion_data_for_leaderboard_query(email_list: list):
144
+ """
145
+ Get the query to fetch the completions data for leaderboard.
146
+
147
+ Query should fetch the completion data for like course completion count of
148
+ the enterprise learners to show in the leaderboard.
149
+
150
+ Arguments:
151
+ email_list (str): List of emails to filter the completions data.
152
+
153
+ Returns:
154
+ (list<str>): Query to fetch the completions data for leaderboard.
155
+ """
156
+ return f"""
157
+ SELECT email, count(course_key) as course_completion_count
158
+ FROM fact_enrollment_admin_dash
159
+ WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
160
+ (passed_date BETWEEN %(start_date)s AND %(end_date)s) AND
161
+ has_passed = 1 AND
162
+ email IN {str(tuple(email_list))}
163
+ GROUP BY email;
164
+ """
165
+
163
166
  @staticmethod
164
167
  def get_leaderboard_data_count_query():
165
168
  """
166
- Get the query to fetch the leaderboard row count.
169
+ Get the query to fetch the leaderboard row count and null email counter.
167
170
 
168
171
  Query should fetch the count of rows for the leaderboard data for the enterprise customer.
169
172
 
@@ -171,26 +174,13 @@ class FactEngagementAdminDashQueries:
171
174
  (str): Query to fetch the leaderboard row count.
172
175
  """
173
176
  return """
174
- WITH Engagement AS (
175
- SELECT
176
- email
177
- FROM fact_enrollment_engagement_day_admin_dash
178
- WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
179
- (activity_date BETWEEN %(start_date)s AND %(end_date)s) AND
180
- is_engaged = 1
181
- GROUP BY email
182
- ),
183
- Completions AS (
184
- SELECT email, count(course_key) as course_completion_count
185
- FROM fact_enrollment_admin_dash
186
- WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
187
- (passed_date BETWEEN %(start_date)s AND %(end_date)s) AND
188
- has_passed = 1
189
- GROUP BY email
190
- )
191
177
  SELECT
192
- count(*)
193
- FROM Engagement
194
- LEFT JOIN Completions
195
- ON Engagement.email = Completions.email
178
+ COUNT(*) OVER () AS record_count,
179
+ sum(case when email is null then 1 else 0 end) null_count
180
+ FROM fact_enrollment_engagement_day_admin_dash
181
+ WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
182
+ (activity_date BETWEEN %(start_date)s AND %(end_date)s) AND
183
+ is_engaged = 1
184
+ GROUP BY email
185
+ LIMIT 1;
196
186
  """
@@ -153,11 +153,14 @@ class FactEngagementAdminDashTable(BaseTable):
153
153
  as_dict=True,
154
154
  )
155
155
 
156
- def get_all_leaderboard_data(
156
+ def _get_engagement_data_for_leaderboard(
157
157
  self, enterprise_customer_uuid: UUID, start_date: date, end_date: date, limit: int, offset: int
158
158
  ):
159
159
  """
160
- Get the leaderboard data for the given enterprise customer.
160
+ Get the engagement data for leaderboard.
161
+
162
+ The engagement data would include fields like learning time, session length of
163
+ the enterprise learners to show in the leaderboard.
161
164
 
162
165
  Arguments:
163
166
  enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
@@ -167,10 +170,10 @@ class FactEngagementAdminDashTable(BaseTable):
167
170
  offset (int): The number of records to skip.
168
171
 
169
172
  Returns:
170
- list[dict]: The leaderboard data.
173
+ list[dict]: The engagement data for leaderboard.
171
174
  """
172
175
  return run_query(
173
- query=self.queries.get_all_leaderboard_data_query(),
176
+ query=self.queries.get_engagement_data_for_leaderboard_query(),
174
177
  params={
175
178
  'enterprise_customer_uuid': enterprise_customer_uuid,
176
179
  'start_date': start_date,
@@ -181,6 +184,70 @@ class FactEngagementAdminDashTable(BaseTable):
181
184
  as_dict=True,
182
185
  )
183
186
 
187
+ def _get_completion_data_for_leaderboard_query(
188
+ self, enterprise_customer_uuid: UUID, start_date: date, end_date: date, email_list: list
189
+ ):
190
+ """
191
+ Get the completion data for leaderboard.
192
+
193
+ The completion data would include fields like course completion count of enterprise learners of the
194
+ given enterprise customer.
195
+
196
+ Arguments:
197
+ enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
198
+ start_date (date): The start date.
199
+ end_date (date): The end date.
200
+ email_list (list<str>): List of emails of the enterprise learners.
201
+
202
+ Returns:
203
+ list[dict]: The engagement data for leaderboard.
204
+ """
205
+ return run_query(
206
+ query=self.queries.get_completion_data_for_leaderboard_query(email_list),
207
+ params={
208
+ 'enterprise_customer_uuid': enterprise_customer_uuid,
209
+ 'start_date': start_date,
210
+ 'end_date': end_date,
211
+ },
212
+ as_dict=True,
213
+ )
214
+
215
+ def get_all_leaderboard_data(
216
+ self, enterprise_customer_uuid: UUID, start_date: date, end_date: date, limit: int, offset: int
217
+ ):
218
+ """
219
+ Get the leaderboard data for the given enterprise customer.
220
+
221
+ Arguments:
222
+ enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
223
+ start_date (date): The start date.
224
+ end_date (date): The end date.
225
+ limit (int): The maximum number of records to return.
226
+ offset (int): The number of records to skip.
227
+
228
+ Returns:
229
+ list[dict]: The leaderboard data.
230
+ """
231
+ engagement_data = self._get_engagement_data_for_leaderboard(
232
+ enterprise_customer_uuid=enterprise_customer_uuid,
233
+ start_date=start_date,
234
+ end_date=end_date,
235
+ limit=limit,
236
+ offset=offset,
237
+ )
238
+ engagement_data_dict = {engagement['email']: engagement for engagement in engagement_data}
239
+ completion_data = self._get_completion_data_for_leaderboard_query(
240
+ enterprise_customer_uuid=enterprise_customer_uuid,
241
+ start_date=start_date,
242
+ end_date=end_date,
243
+ email_list=list(engagement_data_dict.keys()),
244
+ )
245
+ for completion in completion_data:
246
+ email = completion['email']
247
+ engagement_data_dict[email]['course_completion_count'] = completion['course_completion_count']
248
+
249
+ return list(engagement_data_dict.values())
250
+
184
251
  def get_leaderboard_data_count(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
185
252
  """
186
253
  Get the total number of leaderboard records for the given enterprise customer.
@@ -6,7 +6,6 @@ from datetime import date, timedelta
6
6
  from logging import getLogger
7
7
  from uuid import UUID
8
8
 
9
- from edx_django_utils.cache import TieredCache
10
9
  from rest_framework import filters, viewsets
11
10
  from rest_framework.decorators import action
12
11
  from rest_framework.response import Response
@@ -25,7 +24,7 @@ from enterprise_data.filters import AuditEnrollmentsFilterBackend, AuditUsersEnr
25
24
  from enterprise_data.models import EnterpriseLearner, EnterpriseLearnerEnrollment
26
25
  from enterprise_data.paginators import EnterpriseEnrollmentsPagination
27
26
  from enterprise_data.renderers import EnrollmentsCSVRenderer
28
- from enterprise_data.utils import get_cache_key, subtract_one_month
27
+ from enterprise_data.utils import subtract_one_month
29
28
 
30
29
  from .base import EnterpriseViewSetMixin
31
30
 
@@ -83,23 +82,7 @@ class EnterpriseLearnerEnrollmentViewSet(EnterpriseViewSetMixin, viewsets.ReadOn
83
82
 
84
83
  enterprise_customer_uuid = self.kwargs['enterprise_id']
85
84
 
86
- # TODO: Created a ticket ENT0-9531 to fix the cache issue
87
- # Temporary logging to test cache issue
88
- try:
89
- LOGGER.info("Trying to get Learner Enrollment data from Cache")
90
- cache_key = get_cache_key(
91
- resource='enterprise-learner',
92
- enterprise_customer=enterprise_customer_uuid,
93
- )
94
- cached_response = TieredCache.get_cached_response(cache_key)
95
- if cached_response.is_found:
96
- LOGGER.info("Learner Enrollment data found in Cache for Enterprise: [%s]", enterprise_customer_uuid)
97
- else:
98
- LOGGER.info("Learner Enrollment data not found in Cache for Enterprise: [%s]", enterprise_customer_uuid)
99
- TieredCache.set_all_tiers(cache_key, 'dummy_enrollments', DEFAULT_LEARNER_CACHE_TIMEOUT)
100
- LOGGER.info("Cache set for Enterprise: [%s] whose key is: [%s]", enterprise_customer_uuid, cache_key)
101
- except Exception as e:
102
- LOGGER.error("Memcached connection test failed: %s", e)
85
+ # TODO: Created a ticket ENT0-9531 to add the cache on this viewset
103
86
 
104
87
  enrollments = EnterpriseLearnerEnrollment.objects.filter(enterprise_customer_uuid=enterprise_customer_uuid)
105
88
  enrollments = self.apply_filters(enrollments)