edx-enterprise-data 8.9.0__py3-none-any.whl → 8.11.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.
Files changed (27) hide show
  1. {edx_enterprise_data-8.9.0.dist-info → edx_enterprise_data-8.11.0.dist-info}/METADATA +1 -1
  2. {edx_enterprise_data-8.9.0.dist-info → edx_enterprise_data-8.11.0.dist-info}/RECORD +27 -17
  3. enterprise_data/__init__.py +1 -1
  4. enterprise_data/admin_analytics/constants.py +8 -0
  5. enterprise_data/admin_analytics/database/__init__.py +4 -0
  6. enterprise_data/admin_analytics/database/queries/__init__.py +5 -0
  7. enterprise_data/admin_analytics/database/queries/fact_engagement_admin_dash.py +21 -0
  8. enterprise_data/admin_analytics/database/queries/fact_enrollment_admin_dash.py +61 -0
  9. enterprise_data/admin_analytics/database/tables/__init__.py +5 -0
  10. enterprise_data/admin_analytics/database/tables/base.py +18 -0
  11. enterprise_data/admin_analytics/database/tables/fact_engagement_admin_dash.py +38 -0
  12. enterprise_data/admin_analytics/database/tables/fact_enrollment_admin_dash.py +76 -0
  13. enterprise_data/admin_analytics/{database.py → database/utils.py} +3 -2
  14. enterprise_data/api/v1/serializers.py +31 -1
  15. enterprise_data/api/v1/urls.py +14 -0
  16. enterprise_data/api/v1/views/analytics_engagements.py +395 -0
  17. enterprise_data/api/v1/views/analytics_enrollments.py +1 -0
  18. enterprise_data/api/v1/views/analytics_leaderboard.py +4 -1
  19. enterprise_data/api/v1/views/enterprise_admin.py +15 -44
  20. enterprise_data/api/v1/views/enterprise_completions.py +2 -0
  21. enterprise_data/renderers.py +14 -0
  22. enterprise_data/tests/admin_analytics/mock_analytics_data.py +41 -1
  23. enterprise_data/tests/admin_analytics/test_analytics_engagements.py +390 -0
  24. enterprise_data/tests/api/v1/views/test_enterprise_admin.py +43 -20
  25. {edx_enterprise_data-8.9.0.dist-info → edx_enterprise_data-8.11.0.dist-info}/LICENSE +0 -0
  26. {edx_enterprise_data-8.9.0.dist-info → edx_enterprise_data-8.11.0.dist-info}/WHEEL +0 -0
  27. {edx_enterprise_data-8.9.0.dist-info → edx_enterprise_data-8.11.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edx-enterprise-data
3
- Version: 8.9.0
3
+ Version: 8.11.0
4
4
  Summary: Enterprise Reporting
5
5
  Home-page: https://github.com/openedx/edx-enterprise-data
6
6
  Author: edX
@@ -1,20 +1,28 @@
1
- enterprise_data/__init__.py,sha256=Zxnoju6lsQu0H9GDmX4En0Gmk8P-gBTSZJ-96C3W-0E,123
1
+ enterprise_data/__init__.py,sha256=43cEhgzFHOpsMk6l_FF2WJGDjIlxTPg6xfJU8UsyHrA,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
5
5
  enterprise_data/filters.py,sha256=D2EiK12MMpBoz6eOUmTpoJEhj_sH7bA93NRRAdvkDVo,6163
6
6
  enterprise_data/models.py,sha256=khGcOh7NWP8KGu84t78Y2zAu3knREeXA_prApmU2NX8,24428
7
7
  enterprise_data/paginators.py,sha256=YPrC5TeXFt-ymenT2H8H2nCbDCnAzJQlH9kFPElRxWE,269
8
- enterprise_data/renderers.py,sha256=9gIzavWspZTk4vDfVKXJtdn0tSZ2xNgkF-Akf7AWIDM,2389
8
+ enterprise_data/renderers.py,sha256=VaCymaZUhYEZ6yvryoASEohKeeL6lcPSWhFCnyfzjps,2699
9
9
  enterprise_data/signals.py,sha256=8eqNPnlvmfsKf19lGWv5xTIuBgQIqR8EZSp9UYzC8Rc,1024
10
10
  enterprise_data/urls.py,sha256=bqtKF5OEWEwrNmHG3os-pZNuNsmjlhxEqp7yM4TbPf4,243
11
11
  enterprise_data/utils.py,sha256=_zK3BErjZSIkP_JNzK8m-DR5pRTnxKylP9I-vURaRcE,3009
12
12
  enterprise_data/admin_analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  enterprise_data/admin_analytics/completions_utils.py,sha256=kGmLy7x6aD0coNYgzLa5XzJypLkGTT5clDHLSH_QFDE,9442
14
- enterprise_data/admin_analytics/constants.py,sha256=aHDgTHdsjbKNpgtNLDsl4giqhhrRkCGi72ysGIEk0Ao,817
14
+ enterprise_data/admin_analytics/constants.py,sha256=7WturLuMISekgcHHlgj45PPdPrDTYM-l21lA8-Q_Tfc,1107
15
15
  enterprise_data/admin_analytics/data_loaders.py,sha256=4PSsIveNBtpFqwrLUjTl5oywHVYFAMdZrNRHRGMk4XY,6116
16
- enterprise_data/admin_analytics/database.py,sha256=mNS_9xE5h6O7oMMzr6kr6LDTTSNvKzo8vaM-YG8tOd8,1312
17
16
  enterprise_data/admin_analytics/utils.py,sha256=CQuTlg36AALJiopp4us-JN8oTXsw-jDXSJenbphLDME,12270
17
+ enterprise_data/admin_analytics/database/__init__.py,sha256=vNSWKf2VV5xMegN7htJJtxtQEb0ASLC6frE2w0ZpYpE,104
18
+ enterprise_data/admin_analytics/database/utils.py,sha256=Zl-W_w5SVb-QpIwWxbHr0w7z4L2ZFeruJSygWh8g7II,1408
19
+ enterprise_data/admin_analytics/database/queries/__init__.py,sha256=IC5TLOr_GnydbrVbl2mWhwO3aUbYeHuDmfPTLmwGhZA,218
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=X1muOEhEvqD-tyhrVEQkPrf8_7g7SPaJuMwriUPo3jw,2062
22
+ enterprise_data/admin_analytics/database/tables/__init__.py,sha256=3ECKlKlz1wuTER5M57CMFvmLFp0oCnVQXAUeTN96Bs0,213
23
+ enterprise_data/admin_analytics/database/tables/base.py,sha256=1KyKsC18pW3m-5U-T6pdt5rIwsz6Wp3QFFbD3r6L6YQ,395
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=SLnhWEfbQfeaUWT1a7H5ZCTq3XMMrzO_6iG-g6kMry4,2571
18
26
  enterprise_data/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
27
  enterprise_data/api/urls.py,sha256=POqc_KATHdnpMf9zHtpO46pKD5KAlAExtx7G6iylLcU,273
20
28
  enterprise_data/api/v0/__init__.py,sha256=1aAzAYU5hk-RW6cKUxa1645cbZMxn7GIZ7OMjWc9MKI,46
@@ -23,14 +31,15 @@ enterprise_data/api/v0/urls.py,sha256=vzJjqIo_S3AXWs9Us8XTaJc3FnxLbYzAkmLyuDQqum
23
31
  enterprise_data/api/v0/views.py,sha256=4RslZ4NZOU-844bnebEQ71ji2utRY7jEijqC45oQQD0,14380
24
32
  enterprise_data/api/v1/__init__.py,sha256=1aAzAYU5hk-RW6cKUxa1645cbZMxn7GIZ7OMjWc9MKI,46
25
33
  enterprise_data/api/v1/paginators.py,sha256=f0xsilLaU94jSBltJk46tR1rLEIt7YrqSzMAAVtPXjA,3592
26
- enterprise_data/api/v1/serializers.py,sha256=9F2LGa8IKvglgeYNHw3Q0eEZUWknwHZMNZOdpDviEo4,12327
27
- enterprise_data/api/v1/urls.py,sha256=xFsBf3TTsdblFAiHq1Bj3h82Ye1PS3cgqLC0pIso2js,3504
34
+ enterprise_data/api/v1/serializers.py,sha256=Kk4zuRNcr4bfMYIwi2iXQAr_NM3OXuXNfxfrz7xO2iE,13194
35
+ enterprise_data/api/v1/urls.py,sha256=nFcbPSfAIKW6Eiwd1vN0WMqdtBfh9_bBqAFCVrzRm5I,4091
28
36
  enterprise_data/api/v1/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- enterprise_data/api/v1/views/analytics_enrollments.py,sha256=om8i5HTDxDMSny1fy49Wh38LdYLLz-k-oFQJqlQLOxg,16812
30
- enterprise_data/api/v1/views/analytics_leaderboard.py,sha256=EE34fJWYp8OGbIj8oRLlgMhbSm37w98oPXn1aPIZWWE,5860
37
+ enterprise_data/api/v1/views/analytics_engagements.py,sha256=8H3Fk-hTqJaU3H5Lpu1kFWq7p7xDp1pjge-sK7osDbg,17553
38
+ enterprise_data/api/v1/views/analytics_enrollments.py,sha256=trC92GOej6vUoju53KT3dPEDnoPHdukfXEIXPThz76A,16886
39
+ enterprise_data/api/v1/views/analytics_leaderboard.py,sha256=2DALqzUIbe4-ZGgHHIkYAKJ5L1ik2ruPtQNYtTdPba4,5974
31
40
  enterprise_data/api/v1/views/base.py,sha256=FTAxlz5EzvAY657wzVgzhJPFSCHHzct7IDcvm71Smt8,866
32
- enterprise_data/api/v1/views/enterprise_admin.py,sha256=F34FbOz1gLwHPUAQOg3mOjZoKirbCRrjZS2xFJSUBpw,9274
33
- enterprise_data/api/v1/views/enterprise_completions.py,sha256=OkH6eYNql6UGVU-Xjx7PzwzaHeUHfa6e4WJmkUoHGDM,8221
41
+ enterprise_data/api/v1/views/enterprise_admin.py,sha256=_HfQ46bIC6uU3knCWhGLnsWf_YGtsjYHU5UrwG6sdfA,8568
42
+ enterprise_data/api/v1/views/enterprise_completions.py,sha256=bJG2ZtTbLyiBrj64iJHQNHEKLrJCzl9OuJ7nDtw-9aY,8377
34
43
  enterprise_data/api/v1/views/enterprise_learner.py,sha256=yABjJje3CT8I8YOhWr1_tTkdKtnGJom8eu3EFz_-0BU,18517
35
44
  enterprise_data/api/v1/views/enterprise_offers.py,sha256=VifxgqTLFLVw4extYPlHcN1N_yjXcsYsAlYEnAbpb10,1266
36
45
  enterprise_data/fixtures/enterprise_enrollment.json,sha256=6onPXXR29pMdTdbl_mn81sDi3Re5jkLUZz2TPMB_1IY,5786
@@ -104,8 +113,9 @@ enterprise_data/tests/test_models.py,sha256=MWBY-LY5TPBjZ4GlvpM-h4W-BvRKr2Rml8Bz
104
113
  enterprise_data/tests/test_utils.py,sha256=vbmYM7DMN-lHS2p4yaa0Yd6uSGXd2qoZRDE9X3J4Sec,18385
105
114
  enterprise_data/tests/test_views.py,sha256=UvDRNTxruy5zBK_KgUy2cBMbwlaTW_vkM0-TCXbQZiY,69667
106
115
  enterprise_data/tests/admin_analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
- enterprise_data/tests/admin_analytics/mock_analytics_data.py,sha256=mLGTIP89VAQgqKtYlYnKUAKyZATzKnBtI_5aJwMmr7Q,18344
116
+ enterprise_data/tests/admin_analytics/mock_analytics_data.py,sha256=LoYAh5cn_4rv2stGcMP5PELv2l7Eu2DTKG-v7viNTCs,20266
108
117
  enterprise_data/tests/admin_analytics/mock_enrollments.py,sha256=LfuMo9Kn-OQD4z42G3BRuM5MXUUXXlaAMhTqfJf46XE,7266
118
+ enterprise_data/tests/admin_analytics/test_analytics_engagements.py,sha256=KPXtBPaAOrzfff7W-xERSGx9KtZAJndLbIJx3gopSnE,15689
109
119
  enterprise_data/tests/admin_analytics/test_analytics_enrollments.py,sha256=UdKRkP6BNbsSo-gm0YCoddT-ReUMI1x9E6HNLSHT7pY,15177
110
120
  enterprise_data/tests/admin_analytics/test_analytics_leaderboard.py,sha256=VSEyDAHfWBJvqmx9yzd4NnPAqK3TqaKrMBWswMAdzfU,6206
111
121
  enterprise_data/tests/admin_analytics/test_data_loaders.py,sha256=o3denJ4aUS1pI5Crksl4C6m-NtCBm8ynoHBnLkf-v2U,4641
@@ -118,7 +128,7 @@ enterprise_data/tests/api/v1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
118
128
  enterprise_data/tests/api/v1/test_serializers.py,sha256=DwgEHcyOP3oqNUPB2O-NkJGeO_cYs9XJiq7791vJLZE,3682
119
129
  enterprise_data/tests/api/v1/test_views.py,sha256=rLqUHfar0HdBNtz33hQxd_0qUUgr7Ku3KwQSQ1B4Ypg,15213
120
130
  enterprise_data/tests/api/v1/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
- enterprise_data/tests/api/v1/views/test_enterprise_admin.py,sha256=At4g5Q4W4SNPk693HxuoEOHtMehvkscLvtXV4dbivvE,4969
131
+ enterprise_data/tests/api/v1/views/test_enterprise_admin.py,sha256=i0A1JqG1YQTVRiXviFPbx385p7YhMxew72lgTZ7YNEg,6173
122
132
  enterprise_data_roles/__init__.py,sha256=toCpbypm2uDoWVw29_em9gPFNly8vNUS__C0b4TCqEg,112
123
133
  enterprise_data_roles/admin.py,sha256=QNP0VeWE092vZzpyxOA5UJK1nNGl5e71B1J0RCwo_nU,998
124
134
  enterprise_data_roles/apps.py,sha256=nKi8TyuQ5Q6WGtKs5QeXvUTc3N-YQjKhyBnm2EM3Bng,260
@@ -159,8 +169,8 @@ enterprise_reporting/tests/test_send_enterprise_reports.py,sha256=WtL-RqGgu2x5PP
159
169
  enterprise_reporting/tests/test_utils.py,sha256=Zt_TA0LVb-B6fQGkUkAKKVlUKKnQh8jnw1US1jKe7g8,9493
160
170
  enterprise_reporting/tests/test_vertica_client.py,sha256=-R2yNCGUjRtoXwLMBloVFQkFYrJoo613VCr61gwI3kQ,140
161
171
  enterprise_reporting/tests/utils.py,sha256=xms2LM7DV3wczXEfctOK1ddel1EE0J_YSr17UzbCDy4,1401
162
- edx_enterprise_data-8.9.0.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
163
- edx_enterprise_data-8.9.0.dist-info/METADATA,sha256=UTWat3hOmN-XCrlQYPFRaNeyVtqtigs8ZUkDs8dmJWo,1569
164
- edx_enterprise_data-8.9.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
165
- edx_enterprise_data-8.9.0.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
166
- edx_enterprise_data-8.9.0.dist-info/RECORD,,
172
+ edx_enterprise_data-8.11.0.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
173
+ edx_enterprise_data-8.11.0.dist-info/METADATA,sha256=21GMLdFJo9VqGsBOCJgld3rUyVhCwGTZPXEYjPb3Ou4,1570
174
+ edx_enterprise_data-8.11.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
175
+ edx_enterprise_data-8.11.0.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
176
+ edx_enterprise_data-8.11.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__ = "8.9.0"
5
+ __version__ = "8.11.0"
@@ -31,3 +31,11 @@ class ResponseType(Enum):
31
31
  """Response type choices"""
32
32
  JSON = 'json'
33
33
  CSV = 'csv'
34
+
35
+
36
+ class EngagementChart(Enum):
37
+ """Response Choices"""
38
+ ENGAGEMENTS_OVER_TIME = 'engagements_over_time'
39
+ TOP_COURSES_BY_ENGAGEMENTS = 'top_courses_by_engagements'
40
+ TOP_SUBJECTS_BY_ENGAGEMENTS = 'top_subjects_by_engagements'
41
+ INDIVIDUAL_ENGAGEMENTS = 'individual_engagements'
@@ -0,0 +1,4 @@
1
+ """
2
+ This module contains the database queries for the admin analytics.
3
+ """
4
+ from .utils import run_query
@@ -0,0 +1,5 @@
1
+ """
2
+ Module containing queries for the fact_enrollment_admin_dash table.
3
+ """
4
+ from .fact_engagement_admin_dash import FactEngagementAdminDashQueries
5
+ from .fact_enrollment_admin_dash import FactEnrollmentAdminDashQueries
@@ -0,0 +1,21 @@
1
+ """
2
+ Module containing queries for the fact_enrollment_engagement_day_admin_dash table.
3
+ """
4
+
5
+
6
+ class FactEngagementAdminDashQueries:
7
+ """
8
+ Queries related to the fact_enrollment_engagement_day_admin_dash table.
9
+ """
10
+ @staticmethod
11
+ def get_learning_hours_and_daily_sessions_query():
12
+ """
13
+ Get the query to fetch the learning hours and daily sessions.
14
+ """
15
+ return """
16
+ SELECT
17
+ ROUND(SUM(learning_time_seconds) / 60 / 60, 1) as hours, SUM(is_engaged) as sessions
18
+ FROM fact_enrollment_engagement_day_admin_dash
19
+ WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
20
+ activity_date BETWEEN %(start_date)s AND %(end_date)s;
21
+ """
@@ -0,0 +1,61 @@
1
+ """
2
+ Module containing queries for the fact_enrollment_admin_dash table.
3
+ """
4
+
5
+
6
+ class FactEnrollmentAdminDashQueries:
7
+ """
8
+ Queries related to the fact_enrollment_admin_dash table.
9
+ """
10
+
11
+ @staticmethod
12
+ def get_enrollment_date_range_query():
13
+ """
14
+ Get the query to fetch the enrollment date range.
15
+ """
16
+ return """
17
+ SELECT
18
+ MIN(enterprise_enrollment_date) AS min_enrollment_date,
19
+ MAX(enterprise_enrollment_date) AS max_enrollment_date
20
+ FROM fact_enrollment_admin_dash
21
+ WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s;
22
+ """
23
+
24
+ @staticmethod
25
+ def get_enrollment_and_course_count_query():
26
+ """
27
+ Get the query to fetch the enrollment and course count.
28
+ """
29
+ return """
30
+ SELECT
31
+ count(*) as enrolls, count(DISTINCT course_key) as courses
32
+ FROM fact_enrollment_admin_dash
33
+ WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
34
+ enterprise_enrollment_date BETWEEN %(start_date)s AND %(end_date)s;
35
+ """
36
+
37
+ @staticmethod
38
+ def get_completion_count_query():
39
+ """
40
+ Get the query to fetch the completion count.
41
+ """
42
+ return """
43
+ SELECT
44
+ SUM(has_passed) as completions
45
+ FROM fact_enrollment_admin_dash
46
+ WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
47
+ passed_date BETWEEN %(start_date)s AND %(end_date)s;
48
+ """
49
+
50
+ @staticmethod
51
+ def get_learning_hours_and_daily_sessions_query():
52
+ """
53
+ Get the query to fetch the learning hours and daily sessions.
54
+ """
55
+ return """
56
+ SELECT
57
+ ROUND(SUM(learning_time_seconds) / 60 / 60, 1) as hours, SUM(is_engaged) as sessions
58
+ FROM fact_engagement_admin_dash
59
+ WHERE enterprise_customer_uuid=%(enterprise_customer_uuid)s AND
60
+ activity_date BETWEEN %(start_date)s AND %(end_date)s;
61
+ """
@@ -0,0 +1,5 @@
1
+ """
2
+ This module contains the database queries for the admin analytics.
3
+ """
4
+ from .fact_engagement_admin_dash import FactEngagementAdminDashTable
5
+ from .fact_enrollment_admin_dash import FactEnrollmentAdminDashTable
@@ -0,0 +1,18 @@
1
+ """
2
+ Base class to store the table information.
3
+ """
4
+
5
+
6
+ class BaseTable:
7
+ """
8
+ Singleton class to store the table information.
9
+ """
10
+ instance = None
11
+
12
+ def __new__(cls):
13
+ """
14
+ Singleton method to create a single instance of the table.
15
+ """
16
+ if cls.instance is None:
17
+ cls.instance = super(BaseTable, cls).__new__(cls)
18
+ return cls.instance
@@ -0,0 +1,38 @@
1
+ """
2
+ Module for interacting with the fact_enrollment_engagement_day_admin_dash table.
3
+ """
4
+ from datetime import date
5
+ from uuid import UUID
6
+
7
+ from ..queries import FactEngagementAdminDashQueries
8
+ from ..utils import run_query
9
+ from .base import BaseTable
10
+
11
+
12
+ class FactEngagementAdminDashTable(BaseTable):
13
+ """
14
+ Class for communicating with the fact_enrollment_engagement_day_admin_dash table.
15
+ """
16
+ queries = FactEngagementAdminDashQueries()
17
+
18
+ def get_learning_hours_and_daily_sessions(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
19
+ """
20
+ Get the learning hours and daily sessions 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
+ (tuple<float, int>): The learning hours and daily sessions.
29
+ """
30
+ results = run_query(
31
+ query=self.queries.get_learning_hours_and_daily_sessions_query(),
32
+ params={
33
+ 'enterprise_customer_uuid': enterprise_customer_uuid,
34
+ 'start_date': start_date,
35
+ 'end_date': end_date,
36
+ }
37
+ )
38
+ return tuple(results[0])
@@ -0,0 +1,76 @@
1
+ """
2
+ Module for interacting with the fact_enrollment_admin_dash table.
3
+ """
4
+ from datetime import date
5
+ from uuid import UUID
6
+
7
+ from ..queries import FactEnrollmentAdminDashQueries
8
+ from ..utils import run_query
9
+ from .base import BaseTable
10
+
11
+
12
+ class FactEnrollmentAdminDashTable(BaseTable):
13
+ """
14
+ Class for communicating with the fact_enrollment_admin_dash table.
15
+ """
16
+ queries = FactEnrollmentAdminDashQueries()
17
+
18
+ def get_enrollment_date_range(self, enterprise_customer_uuid: UUID):
19
+ """
20
+ Get the enrollment date range for the given enterprise customer.
21
+
22
+ Arguments:
23
+ enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
24
+
25
+ Returns:
26
+ (tuple<int, int>): The minimum and maximum enrollment dates.
27
+ """
28
+ results = run_query(
29
+ query=self.queries.get_enrollment_date_range_query(),
30
+ params={'enterprise_customer_uuid': enterprise_customer_uuid}
31
+ )
32
+ return tuple(results[0])
33
+
34
+ def get_enrollment_and_course_count(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
35
+ """
36
+ Get the enrollment and course count for the given enterprise customer.
37
+
38
+ Arguments:
39
+ enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
40
+ start_date (date): The start date.
41
+ end_date (date): The end date.
42
+
43
+ Returns:
44
+ (tuple<int, int>): The enrollment and course count.
45
+ """
46
+ results = run_query(
47
+ query=self.queries.get_enrollment_and_course_count_query(),
48
+ params={
49
+ 'enterprise_customer_uuid': enterprise_customer_uuid,
50
+ 'start_date': start_date,
51
+ 'end_date': end_date,
52
+ }
53
+ )
54
+ return tuple(results[0])
55
+
56
+ def get_completion_count(self, enterprise_customer_uuid: UUID, start_date: date, end_date: date):
57
+ """
58
+ Get the completion count for the given enterprise customer.
59
+
60
+ Arguments:
61
+ enterprise_customer_uuid (UUID): The UUID of the enterprise customer.
62
+ start_date (date): The start date.
63
+ end_date (date): The end date.
64
+
65
+ Returns:
66
+ int: The completion count.
67
+ """
68
+ results = run_query(
69
+ query=self.queries.get_completion_count_query(),
70
+ params={
71
+ 'enterprise_customer_uuid': enterprise_customer_uuid,
72
+ 'start_date': start_date,
73
+ 'end_date': end_date,
74
+ }
75
+ )
76
+ return results[0][0]
@@ -30,12 +30,13 @@ def get_db_connection(database=settings.ENTERPRISE_REPORTING_DB_ALIAS):
30
30
 
31
31
 
32
32
  @timeit
33
- def run_query(query):
33
+ def run_query(query, params: dict = None):
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
+ params (dict): The parameters to pass to the query.
39
40
 
40
41
  Returns:
41
42
  (list): The results of the query.
@@ -43,7 +44,7 @@ def run_query(query):
43
44
  try:
44
45
  with closing(get_db_connection()) as connection:
45
46
  with closing(connection.cursor()) as cursor:
46
- cursor.execute(query)
47
+ cursor.execute(query, params=params)
47
48
  return cursor.fetchall()
48
49
  except Exception:
49
50
  LOGGER.exception(f'[run_query]: run_query failed for query "{query}".')
@@ -5,7 +5,13 @@ from uuid import UUID
5
5
 
6
6
  from rest_framework import serializers
7
7
 
8
- from enterprise_data.admin_analytics.constants import Calculation, EnrollmentChart, Granularity, ResponseType
8
+ from enterprise_data.admin_analytics.constants import (
9
+ Calculation,
10
+ EngagementChart,
11
+ EnrollmentChart,
12
+ Granularity,
13
+ ResponseType,
14
+ )
9
15
  from enterprise_data.models import (
10
16
  EnterpriseAdminLearnerProgress,
11
17
  EnterpriseAdminSummarizeInsights,
@@ -331,3 +337,27 @@ class AdvanceAnalyticsEnrollmentStatsSerializer(
331
337
  if value not in self.CHART_TYPES:
332
338
  raise serializers.ValidationError(f"chart_type must be one of {self.CHART_TYPES}")
333
339
  return value
340
+
341
+
342
+ class AdvanceAnalyticsEngagementStatsSerializer(
343
+ AdvanceAnalyticsQueryParamSerializer
344
+ ): # pylint: disable=abstract-method
345
+ """Serializer for validating Advance Analytics Engagements Stats API"""
346
+ CHART_TYPES = [
347
+ EngagementChart.ENGAGEMENTS_OVER_TIME.value,
348
+ EngagementChart.TOP_COURSES_BY_ENGAGEMENTS.value,
349
+ EngagementChart.TOP_SUBJECTS_BY_ENGAGEMENTS.value
350
+ ]
351
+
352
+ chart_type = serializers.CharField(required=False)
353
+
354
+ def validate_chart_type(self, value):
355
+ """
356
+ Validate the chart_type value.
357
+
358
+ Raises:
359
+ serializers.ValidationError: If chart_type is not one of the valid choices
360
+ """
361
+ if value not in self.CHART_TYPES:
362
+ raise serializers.ValidationError(f"chart_type must be one of {self.CHART_TYPES}")
363
+ return value
@@ -11,6 +11,10 @@ from enterprise_data.api.v1.views import enterprise_admin as enterprise_admin_vi
11
11
  from enterprise_data.api.v1.views import enterprise_completions as enterprise_completions_views
12
12
  from enterprise_data.api.v1.views import enterprise_learner as enterprise_learner_views
13
13
  from enterprise_data.api.v1.views import enterprise_offers as enterprise_offers_views
14
+ from enterprise_data.api.v1.views.analytics_engagements import (
15
+ AdvanceAnalyticsEngagementStatsView,
16
+ AdvanceAnalyticsIndividualEngagementsView,
17
+ )
14
18
  from enterprise_data.api.v1.views.analytics_enrollments import (
15
19
  AdvanceAnalyticsEnrollmentStatsView,
16
20
  AdvanceAnalyticsIndividualEnrollmentsView,
@@ -73,6 +77,16 @@ urlpatterns = [
73
77
  AdvanceAnalyticsIndividualEnrollmentsView.as_view(),
74
78
  name='enterprise-admin-analytics-enrollments'
75
79
  ),
80
+ re_path(
81
+ fr'^admin/analytics/(?P<enterprise_uuid>{UUID4_REGEX})/engagements/stats$',
82
+ AdvanceAnalyticsEngagementStatsView.as_view(),
83
+ name='enterprise-admin-analytics-engagements-stats'
84
+ ),
85
+ re_path(
86
+ fr'^admin/analytics/(?P<enterprise_uuid>{UUID4_REGEX})/engagements$',
87
+ AdvanceAnalyticsIndividualEngagementsView.as_view(),
88
+ name='enterprise-admin-analytics-engagements'
89
+ ),
76
90
  re_path(
77
91
  fr'^admin/analytics/(?P<enterprise_id>{UUID4_REGEX})/skills/stats',
78
92
  enterprise_admin_views.EnterpriseAdminAnalyticsSkillsView.as_view(),