edx-enterprise-data 8.11.0__py3-none-any.whl → 8.12.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.
- {edx_enterprise_data-8.11.0.dist-info → edx_enterprise_data-8.12.0.dist-info}/METADATA +1 -1
- {edx_enterprise_data-8.11.0.dist-info → edx_enterprise_data-8.12.0.dist-info}/RECORD +16 -16
- enterprise_data/__init__.py +1 -1
- enterprise_data/admin_analytics/database/queries/fact_enrollment_admin_dash.py +78 -0
- enterprise_data/admin_analytics/database/tables/fact_enrollment_admin_dash.py +128 -3
- enterprise_data/admin_analytics/database/utils.py +8 -3
- enterprise_data/api/v1/serializers.py +2 -0
- enterprise_data/api/v1/urls.py +3 -6
- enterprise_data/api/v1/views/analytics_enrollments.py +90 -332
- enterprise_data/api/v1/views/base.py +79 -0
- enterprise_data/api/v1/views/enterprise_admin.py +5 -3
- enterprise_data/tests/admin_analytics/mock_analytics_data.py +0 -12
- enterprise_data/tests/admin_analytics/test_analytics_enrollments.py +72 -115
- {edx_enterprise_data-8.11.0.dist-info → edx_enterprise_data-8.12.0.dist-info}/LICENSE +0 -0
- {edx_enterprise_data-8.11.0.dist-info → edx_enterprise_data-8.12.0.dist-info}/WHEEL +0 -0
- {edx_enterprise_data-8.11.0.dist-info → edx_enterprise_data-8.12.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
enterprise_data/__init__.py,sha256=
|
1
|
+
enterprise_data/__init__.py,sha256=6EwDYR1Ig68WDaZhWEMjK_4a3LbkjyRay9rmzaGXfPE,124
|
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,14 +15,14 @@ enterprise_data/admin_analytics/constants.py,sha256=7WturLuMISekgcHHlgj45PPdPrDT
|
|
15
15
|
enterprise_data/admin_analytics/data_loaders.py,sha256=4PSsIveNBtpFqwrLUjTl5oywHVYFAMdZrNRHRGMk4XY,6116
|
16
16
|
enterprise_data/admin_analytics/utils.py,sha256=CQuTlg36AALJiopp4us-JN8oTXsw-jDXSJenbphLDME,12270
|
17
17
|
enterprise_data/admin_analytics/database/__init__.py,sha256=vNSWKf2VV5xMegN7htJJtxtQEb0ASLC6frE2w0ZpYpE,104
|
18
|
-
enterprise_data/admin_analytics/database/utils.py,sha256=
|
18
|
+
enterprise_data/admin_analytics/database/utils.py,sha256=5u-d6ZQW95mF_r4bH8Xdi7DgpYAuDFOG_q0P-bjKXHU,1712
|
19
19
|
enterprise_data/admin_analytics/database/queries/__init__.py,sha256=IC5TLOr_GnydbrVbl2mWhwO3aUbYeHuDmfPTLmwGhZA,218
|
20
20
|
enterprise_data/admin_analytics/database/queries/fact_engagement_admin_dash.py,sha256=fq01Ni_sKnvSRoiPQfTnJ8TtRePQe5MBLmI5CpVy36o,747
|
21
|
-
enterprise_data/admin_analytics/database/queries/fact_enrollment_admin_dash.py,sha256=
|
21
|
+
enterprise_data/admin_analytics/database/queries/fact_enrollment_admin_dash.py,sha256=ofV4uYgMC_quHxDFPV_3UTeKffjgcm6ri68VSVelKe4,5425
|
22
22
|
enterprise_data/admin_analytics/database/tables/__init__.py,sha256=3ECKlKlz1wuTER5M57CMFvmLFp0oCnVQXAUeTN96Bs0,213
|
23
23
|
enterprise_data/admin_analytics/database/tables/base.py,sha256=1KyKsC18pW3m-5U-T6pdt5rIwsz6Wp3QFFbD3r6L6YQ,395
|
24
24
|
enterprise_data/admin_analytics/database/tables/fact_engagement_admin_dash.py,sha256=EsG8KgRW84wtA_nJuUknjLYlDtaPSJf_9mWdkO2Bj2I,1293
|
25
|
-
enterprise_data/admin_analytics/database/tables/fact_enrollment_admin_dash.py,sha256=
|
25
|
+
enterprise_data/admin_analytics/database/tables/fact_enrollment_admin_dash.py,sha256=ix5QvPnrUZMVs_Fdt742i9PAmrQTXuqHlfW3PJhSQWo,7282
|
26
26
|
enterprise_data/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
27
|
enterprise_data/api/urls.py,sha256=POqc_KATHdnpMf9zHtpO46pKD5KAlAExtx7G6iylLcU,273
|
28
28
|
enterprise_data/api/v0/__init__.py,sha256=1aAzAYU5hk-RW6cKUxa1645cbZMxn7GIZ7OMjWc9MKI,46
|
@@ -31,14 +31,14 @@ enterprise_data/api/v0/urls.py,sha256=vzJjqIo_S3AXWs9Us8XTaJc3FnxLbYzAkmLyuDQqum
|
|
31
31
|
enterprise_data/api/v0/views.py,sha256=4RslZ4NZOU-844bnebEQ71ji2utRY7jEijqC45oQQD0,14380
|
32
32
|
enterprise_data/api/v1/__init__.py,sha256=1aAzAYU5hk-RW6cKUxa1645cbZMxn7GIZ7OMjWc9MKI,46
|
33
33
|
enterprise_data/api/v1/paginators.py,sha256=f0xsilLaU94jSBltJk46tR1rLEIt7YrqSzMAAVtPXjA,3592
|
34
|
-
enterprise_data/api/v1/serializers.py,sha256=
|
35
|
-
enterprise_data/api/v1/urls.py,sha256=
|
34
|
+
enterprise_data/api/v1/serializers.py,sha256=FEuH-_iTlKFJoxM8ABzEYHDAWHsgSYfdQd2WSPdXoeE,13329
|
35
|
+
enterprise_data/api/v1/urls.py,sha256=JzaaVsHEAELMLFdhR60_8LRLb9klDeA4zdH1dLxnQEo,4048
|
36
36
|
enterprise_data/api/v1/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
37
|
enterprise_data/api/v1/views/analytics_engagements.py,sha256=8H3Fk-hTqJaU3H5Lpu1kFWq7p7xDp1pjge-sK7osDbg,17553
|
38
|
-
enterprise_data/api/v1/views/analytics_enrollments.py,sha256=
|
38
|
+
enterprise_data/api/v1/views/analytics_enrollments.py,sha256=nT3eu336mtjZuAXYRGhugxAY_G3BWPkyf0TtybRe_HM,6249
|
39
39
|
enterprise_data/api/v1/views/analytics_leaderboard.py,sha256=2DALqzUIbe4-ZGgHHIkYAKJ5L1ik2ruPtQNYtTdPba4,5974
|
40
|
-
enterprise_data/api/v1/views/base.py,sha256=
|
41
|
-
enterprise_data/api/v1/views/enterprise_admin.py,sha256=
|
40
|
+
enterprise_data/api/v1/views/base.py,sha256=5fXUH3Q3J6t_GJ-Hb3TFOAC_BUED9SiCk-eGzvNqDRE,3395
|
41
|
+
enterprise_data/api/v1/views/enterprise_admin.py,sha256=d79WkyBbqLk6pKGWWrnbYdrbOgQztP03Q7NKRA5tZB4,8639
|
42
42
|
enterprise_data/api/v1/views/enterprise_completions.py,sha256=bJG2ZtTbLyiBrj64iJHQNHEKLrJCzl9OuJ7nDtw-9aY,8377
|
43
43
|
enterprise_data/api/v1/views/enterprise_learner.py,sha256=yABjJje3CT8I8YOhWr1_tTkdKtnGJom8eu3EFz_-0BU,18517
|
44
44
|
enterprise_data/api/v1/views/enterprise_offers.py,sha256=VifxgqTLFLVw4extYPlHcN1N_yjXcsYsAlYEnAbpb10,1266
|
@@ -113,10 +113,10 @@ enterprise_data/tests/test_models.py,sha256=MWBY-LY5TPBjZ4GlvpM-h4W-BvRKr2Rml8Bz
|
|
113
113
|
enterprise_data/tests/test_utils.py,sha256=vbmYM7DMN-lHS2p4yaa0Yd6uSGXd2qoZRDE9X3J4Sec,18385
|
114
114
|
enterprise_data/tests/test_views.py,sha256=UvDRNTxruy5zBK_KgUy2cBMbwlaTW_vkM0-TCXbQZiY,69667
|
115
115
|
enterprise_data/tests/admin_analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
116
|
-
enterprise_data/tests/admin_analytics/mock_analytics_data.py,sha256=
|
116
|
+
enterprise_data/tests/admin_analytics/mock_analytics_data.py,sha256=VZHhMKSQn5S-o1wNReSVyEnI_-6EkW-TUV5EvXCl5is,19536
|
117
117
|
enterprise_data/tests/admin_analytics/mock_enrollments.py,sha256=LfuMo9Kn-OQD4z42G3BRuM5MXUUXXlaAMhTqfJf46XE,7266
|
118
118
|
enterprise_data/tests/admin_analytics/test_analytics_engagements.py,sha256=KPXtBPaAOrzfff7W-xERSGx9KtZAJndLbIJx3gopSnE,15689
|
119
|
-
enterprise_data/tests/admin_analytics/test_analytics_enrollments.py,sha256=
|
119
|
+
enterprise_data/tests/admin_analytics/test_analytics_enrollments.py,sha256=GePv5E8BRGRWUHUwGaXvYIsN3dtDpNXUh-yfW5iBTi4,13781
|
120
120
|
enterprise_data/tests/admin_analytics/test_analytics_leaderboard.py,sha256=VSEyDAHfWBJvqmx9yzd4NnPAqK3TqaKrMBWswMAdzfU,6206
|
121
121
|
enterprise_data/tests/admin_analytics/test_data_loaders.py,sha256=o3denJ4aUS1pI5Crksl4C6m-NtCBm8ynoHBnLkf-v2U,4641
|
122
122
|
enterprise_data/tests/admin_analytics/test_enterprise_completions.py,sha256=afkHQFy4bvqZ0pq5Drl1t2nv8zxbgca2jzOQbihlPG0,7359
|
@@ -169,8 +169,8 @@ enterprise_reporting/tests/test_send_enterprise_reports.py,sha256=WtL-RqGgu2x5PP
|
|
169
169
|
enterprise_reporting/tests/test_utils.py,sha256=Zt_TA0LVb-B6fQGkUkAKKVlUKKnQh8jnw1US1jKe7g8,9493
|
170
170
|
enterprise_reporting/tests/test_vertica_client.py,sha256=-R2yNCGUjRtoXwLMBloVFQkFYrJoo613VCr61gwI3kQ,140
|
171
171
|
enterprise_reporting/tests/utils.py,sha256=xms2LM7DV3wczXEfctOK1ddel1EE0J_YSr17UzbCDy4,1401
|
172
|
-
edx_enterprise_data-8.
|
173
|
-
edx_enterprise_data-8.
|
174
|
-
edx_enterprise_data-8.
|
175
|
-
edx_enterprise_data-8.
|
176
|
-
edx_enterprise_data-8.
|
172
|
+
edx_enterprise_data-8.12.0.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
|
173
|
+
edx_enterprise_data-8.12.0.dist-info/METADATA,sha256=ePpHvJ_L1ZArGfUBHXEcPExU5vTGx17l-HvK14USLIo,1570
|
174
|
+
edx_enterprise_data-8.12.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
175
|
+
edx_enterprise_data-8.12.0.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
|
176
|
+
edx_enterprise_data-8.12.0.dist-info/RECORD,,
|
enterprise_data/__init__.py
CHANGED
@@ -7,6 +7,30 @@ class FactEnrollmentAdminDashQueries:
|
|
7
7
|
"""
|
8
8
|
Queries related to the fact_enrollment_admin_dash table.
|
9
9
|
"""
|
10
|
+
@staticmethod
|
11
|
+
def get_enrollment_count_query():
|
12
|
+
"""
|
13
|
+
Get the query to fetch the total number of enrollments for an enterprise customer.
|
14
|
+
"""
|
15
|
+
return """
|
16
|
+
SELECT count(*)
|
17
|
+
FROM fact_enrollment_admin_dash
|
18
|
+
WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
|
19
|
+
enterprise_enrollment_date BETWEEN %(start_date)s AND %(end_date)s;
|
20
|
+
"""
|
21
|
+
|
22
|
+
@staticmethod
|
23
|
+
def get_all_enrollments_query():
|
24
|
+
"""
|
25
|
+
Get the query to fetch all enrollments.
|
26
|
+
"""
|
27
|
+
return """
|
28
|
+
SELECT email, course_title, course_subject, enroll_type, enterprise_enrollment_date
|
29
|
+
FROM fact_enrollment_admin_dash
|
30
|
+
WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
|
31
|
+
enterprise_enrollment_date BETWEEN %(start_date)s AND %(end_date)s
|
32
|
+
ORDER BY ENTERPRISE_ENROLLMENT_DATE DESC LIMIT %(limit)s OFFSET %(offset)s
|
33
|
+
"""
|
10
34
|
|
11
35
|
@staticmethod
|
12
36
|
def get_enrollment_date_range_query():
|
@@ -59,3 +83,57 @@ class FactEnrollmentAdminDashQueries:
|
|
59
83
|
WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
|
60
84
|
activity_date BETWEEN %(start_date)s AND %(end_date)s;
|
61
85
|
"""
|
86
|
+
|
87
|
+
@staticmethod
|
88
|
+
def get_top_courses_enrollments_query(record_count=20):
|
89
|
+
"""
|
90
|
+
Get the query to fetch the enrollment count by courses.
|
91
|
+
|
92
|
+
Query will fetch the top N courses by enrollment count. Where N is the value of record_count.
|
93
|
+
|
94
|
+
Arguments:
|
95
|
+
record_count (int): Number of records to fetch.
|
96
|
+
"""
|
97
|
+
# Some local environments raise error when course_title is added in SELECT without GROUP BY.
|
98
|
+
# If you face this issue, you can remove course_title from SELECT.
|
99
|
+
|
100
|
+
# TODO: Re-add course_title after testing.
|
101
|
+
return f"""
|
102
|
+
SELECT course_key, enroll_type, count(course_key) as enrollment_count
|
103
|
+
FROM fact_enrollment_admin_dash
|
104
|
+
WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
|
105
|
+
enterprise_enrollment_date BETWEEN %(start_date)s AND %(end_date)s
|
106
|
+
GROUP BY course_key, enroll_type ORDER BY enrollment_count DESC LIMIT {record_count};
|
107
|
+
"""
|
108
|
+
|
109
|
+
@staticmethod
|
110
|
+
def get_top_subjects_by_enrollments_query(record_count=20):
|
111
|
+
"""
|
112
|
+
Get the query to fetch the enrollment count by subjects.
|
113
|
+
|
114
|
+
Query will fetch the top N subjects by enrollment count. Where N is the value of record_count.
|
115
|
+
|
116
|
+
Arguments:
|
117
|
+
record_count (int): Number of records to fetch.
|
118
|
+
"""
|
119
|
+
return f"""
|
120
|
+
SELECT course_subject, enroll_type, count(course_subject) enrollment_count
|
121
|
+
FROM fact_enrollment_admin_dash
|
122
|
+
WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
|
123
|
+
enterprise_enrollment_date BETWEEN %(start_date)s AND %(end_date)s
|
124
|
+
GROUP BY course_subject, enroll_type ORDER BY enrollment_count DESC LIMIT {record_count};
|
125
|
+
"""
|
126
|
+
|
127
|
+
@staticmethod
|
128
|
+
def get_enrolment_time_series_data_query():
|
129
|
+
"""
|
130
|
+
Get the query to fetch the enrollment time series data with daily aggregation.
|
131
|
+
"""
|
132
|
+
return """
|
133
|
+
SELECT enterprise_enrollment_date, enroll_type, COUNT(*) as enrollment_count
|
134
|
+
FROM fact_enrollment_admin_dash
|
135
|
+
WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
|
136
|
+
enterprise_enrollment_date BETWEEN %(start_date)s AND %(end_date)s
|
137
|
+
GROUP BY enterprise_enrollment_date, enroll_type
|
138
|
+
ORDER BY enterprise_enrollment_date;
|
139
|
+
"""
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
Module for interacting with the fact_enrollment_admin_dash table.
|
3
3
|
"""
|
4
|
-
from datetime import date
|
4
|
+
from datetime import date, datetime
|
5
5
|
from uuid import UUID
|
6
6
|
|
7
7
|
from ..queries import FactEnrollmentAdminDashQueries
|
@@ -15,6 +15,56 @@ class FactEnrollmentAdminDashTable(BaseTable):
|
|
15
15
|
"""
|
16
16
|
queries = FactEnrollmentAdminDashQueries()
|
17
17
|
|
18
|
+
def get_enrollment_count(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
|
19
|
+
"""
|
20
|
+
Get the total number of enrollments for the given enterprise customer.
|
21
|
+
|
22
|
+
Arguments:
|
23
|
+
enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
|
24
|
+
start_date (date): The start date.
|
25
|
+
end_date (date): The end date.
|
26
|
+
|
27
|
+
Returns:
|
28
|
+
(int): The total number of enrollments.
|
29
|
+
"""
|
30
|
+
results = run_query(
|
31
|
+
query=self.queries.get_enrollment_count_query(),
|
32
|
+
params={
|
33
|
+
'enterprise_customer_uuid': enterprise_customer_uuid,
|
34
|
+
'start_date': start_date,
|
35
|
+
'end_date': end_date,
|
36
|
+
}
|
37
|
+
)
|
38
|
+
return results[0][0]
|
39
|
+
|
40
|
+
def get_all_enrollments(
|
41
|
+
self, enterprise_customer_uuid: UUID, start_date: date, end_date: date, limit: int, offset: int
|
42
|
+
):
|
43
|
+
"""
|
44
|
+
Get all enrollments for the given enterprise customer.
|
45
|
+
|
46
|
+
Arguments:
|
47
|
+
enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
|
48
|
+
start_date (date): The start date.
|
49
|
+
end_date (date): The end date.
|
50
|
+
limit (int): The maximum number of records to return.
|
51
|
+
offset (int): The number of records to skip.
|
52
|
+
|
53
|
+
Returns:
|
54
|
+
list<dict>: A list of dictionaries containing the enrollment data.
|
55
|
+
"""
|
56
|
+
return run_query(
|
57
|
+
query=self.queries.get_all_enrollments_query(),
|
58
|
+
params={
|
59
|
+
'enterprise_customer_uuid': enterprise_customer_uuid,
|
60
|
+
'start_date': start_date,
|
61
|
+
'end_date': end_date,
|
62
|
+
'limit': limit,
|
63
|
+
'offset': offset,
|
64
|
+
},
|
65
|
+
as_dict=True,
|
66
|
+
)
|
67
|
+
|
18
68
|
def get_enrollment_date_range(self, enterprise_customer_uuid: UUID):
|
19
69
|
"""
|
20
70
|
Get the enrollment date range for the given enterprise customer.
|
@@ -23,13 +73,22 @@ class FactEnrollmentAdminDashTable(BaseTable):
|
|
23
73
|
enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
|
24
74
|
|
25
75
|
Returns:
|
26
|
-
(tuple<
|
76
|
+
(tuple<date, date>): The minimum and maximum enrollment dates.
|
27
77
|
"""
|
28
78
|
results = run_query(
|
29
79
|
query=self.queries.get_enrollment_date_range_query(),
|
30
80
|
params={'enterprise_customer_uuid': enterprise_customer_uuid}
|
31
81
|
)
|
32
|
-
|
82
|
+
min_date, max_date = results[0]
|
83
|
+
|
84
|
+
# We should return date objects, not datetime objects
|
85
|
+
# This is done to counter cases where database values are datetime objects.
|
86
|
+
if min_date and isinstance(min_date, datetime):
|
87
|
+
min_date = min_date.date()
|
88
|
+
if max_date and isinstance(max_date, datetime):
|
89
|
+
max_date = max_date.date()
|
90
|
+
|
91
|
+
return min_date, max_date
|
33
92
|
|
34
93
|
def get_enrollment_and_course_count(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
|
35
94
|
"""
|
@@ -74,3 +133,69 @@ class FactEnrollmentAdminDashTable(BaseTable):
|
|
74
133
|
}
|
75
134
|
)
|
76
135
|
return results[0][0]
|
136
|
+
|
137
|
+
def get_top_courses_by_enrollments(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
|
138
|
+
"""
|
139
|
+
Get the top courses enrollments for the given enterprise customer.
|
140
|
+
|
141
|
+
Arguments:
|
142
|
+
enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
|
143
|
+
start_date (date): The start date.
|
144
|
+
end_date (date): The end date.
|
145
|
+
|
146
|
+
Returns:
|
147
|
+
list<dict>: A list of dictionaries containing the course key, course_title and enrollment count.
|
148
|
+
"""
|
149
|
+
return run_query(
|
150
|
+
query=self.queries.get_top_courses_enrollments_query(),
|
151
|
+
params={
|
152
|
+
'enterprise_customer_uuid': enterprise_customer_uuid,
|
153
|
+
'start_date': start_date,
|
154
|
+
'end_date': end_date,
|
155
|
+
},
|
156
|
+
as_dict=True,
|
157
|
+
)
|
158
|
+
|
159
|
+
def get_top_subjects_by_enrollments(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
|
160
|
+
"""
|
161
|
+
Get the top subjects by enrollments for the given enterprise customer.
|
162
|
+
|
163
|
+
Arguments:
|
164
|
+
enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
|
165
|
+
start_date (date): The start date.
|
166
|
+
end_date (date): The end date.
|
167
|
+
|
168
|
+
Returns:
|
169
|
+
list<dict>: A list of dictionaries containing the subject and enrollment count.
|
170
|
+
"""
|
171
|
+
return run_query(
|
172
|
+
query=self.queries.get_top_subjects_by_enrollments_query(),
|
173
|
+
params={
|
174
|
+
'enterprise_customer_uuid': enterprise_customer_uuid,
|
175
|
+
'start_date': start_date,
|
176
|
+
'end_date': end_date,
|
177
|
+
},
|
178
|
+
as_dict=True,
|
179
|
+
)
|
180
|
+
|
181
|
+
def get_enrolment_time_series_data(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
|
182
|
+
"""
|
183
|
+
Get the enrollment time series data for the given enterprise customer.
|
184
|
+
|
185
|
+
Arguments:
|
186
|
+
enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
|
187
|
+
start_date (date): The start date.
|
188
|
+
end_date (date): The end date.
|
189
|
+
|
190
|
+
Returns:
|
191
|
+
list<dict>: A list of dictionaries containing the date and enrollment count.
|
192
|
+
"""
|
193
|
+
return run_query(
|
194
|
+
query=self.queries.get_enrolment_time_series_data_query(),
|
195
|
+
params={
|
196
|
+
'enterprise_customer_uuid': enterprise_customer_uuid,
|
197
|
+
'start_date': start_date,
|
198
|
+
'end_date': end_date,
|
199
|
+
},
|
200
|
+
as_dict=True,
|
201
|
+
)
|
@@ -30,22 +30,27 @@ def get_db_connection(database=settings.ENTERPRISE_REPORTING_DB_ALIAS):
|
|
30
30
|
|
31
31
|
|
32
32
|
@timeit
|
33
|
-
def run_query(query, params: dict = None):
|
33
|
+
def run_query(query, params: dict = None, as_dict=False):
|
34
34
|
"""
|
35
35
|
Run a query on the database and return the results.
|
36
36
|
|
37
37
|
Arguments:
|
38
38
|
query (str): The query to run.
|
39
39
|
params (dict): The parameters to pass to the query.
|
40
|
+
as_dict (bool): When True, return the results as a dictionary.
|
40
41
|
|
41
42
|
Returns:
|
42
|
-
(list): The results of the query.
|
43
|
+
(list | dict): The results of the query.
|
43
44
|
"""
|
44
45
|
try:
|
45
46
|
with closing(get_db_connection()) as connection:
|
46
47
|
with closing(connection.cursor()) as cursor:
|
47
48
|
cursor.execute(query, params=params)
|
48
|
-
|
49
|
+
if as_dict:
|
50
|
+
columns = [column[0] for column in cursor.description]
|
51
|
+
return [dict(zip(columns, row)) for row in cursor.fetchall()]
|
52
|
+
else:
|
53
|
+
return cursor.fetchall()
|
49
54
|
except Exception:
|
50
55
|
LOGGER.exception(f'[run_query]: run_query failed for query "{query}".')
|
51
56
|
raise
|
@@ -265,6 +265,8 @@ class AdvanceAnalyticsQueryParamSerializer(serializers.Serializer): # pylint: d
|
|
265
265
|
granularity = serializers.CharField(required=False)
|
266
266
|
calculation = serializers.CharField(required=False)
|
267
267
|
response_type = serializers.CharField(required=False)
|
268
|
+
page = serializers.IntegerField(required=False, min_value=1)
|
269
|
+
page_size = serializers.IntegerField(required=False, min_value=2)
|
268
270
|
|
269
271
|
def validate(self, attrs):
|
270
272
|
"""
|
enterprise_data/api/v1/urls.py
CHANGED
@@ -15,10 +15,7 @@ from enterprise_data.api.v1.views.analytics_engagements import (
|
|
15
15
|
AdvanceAnalyticsEngagementStatsView,
|
16
16
|
AdvanceAnalyticsIndividualEngagementsView,
|
17
17
|
)
|
18
|
-
from enterprise_data.api.v1.views.analytics_enrollments import
|
19
|
-
AdvanceAnalyticsEnrollmentStatsView,
|
20
|
-
AdvanceAnalyticsIndividualEnrollmentsView,
|
21
|
-
)
|
18
|
+
from enterprise_data.api.v1.views.analytics_enrollments import AdvanceAnalyticsEnrollmentsView
|
22
19
|
from enterprise_data.api.v1.views.analytics_leaderboard import AdvanceAnalyticsLeaderboardView
|
23
20
|
from enterprise_data.constants import UUID4_REGEX
|
24
21
|
|
@@ -69,12 +66,12 @@ urlpatterns = [
|
|
69
66
|
),
|
70
67
|
re_path(
|
71
68
|
fr'^admin/analytics/(?P<enterprise_uuid>{UUID4_REGEX})/enrollments/stats$',
|
72
|
-
|
69
|
+
AdvanceAnalyticsEnrollmentsView.as_view({'get': 'stats'}),
|
73
70
|
name='enterprise-admin-analytics-enrollments-stats'
|
74
71
|
),
|
75
72
|
re_path(
|
76
73
|
fr'^admin/analytics/(?P<enterprise_uuid>{UUID4_REGEX})/enrollments$',
|
77
|
-
|
74
|
+
AdvanceAnalyticsEnrollmentsView.as_view({'get': 'list'}),
|
78
75
|
name='enterprise-admin-analytics-enrollments'
|
79
76
|
),
|
80
77
|
re_path(
|