edx-enterprise-data 10.9.0__py3-none-any.whl → 10.9.2__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.2
2
2
  Name: edx-enterprise-data
3
- Version: 10.9.0
3
+ Version: 10.9.2
4
4
  Summary: Enterprise Reporting
5
5
  Home-page: https://github.com/openedx/edx-enterprise-data
6
6
  Author: edX
@@ -1,11 +1,11 @@
1
- enterprise_data/__init__.py,sha256=UwYFZZ5SB1CmFuUuIeKl_NL-ffrcEjblqhv-XQmU8RI,124
1
+ enterprise_data/__init__.py,sha256=43SJnms4n0HahLVcyoeoXg5lGi892WKLrR8LP-MkYto,124
2
2
  enterprise_data/apps.py,sha256=aF6hZwDfI2oWj95tUTm_2ikHueQj-jLj-u0GrgzpsQI,414
3
3
  enterprise_data/clients.py,sha256=pBuCQOP7NYl264ZbMtZCRPCET1pg0by8w6PVlA-icKA,4995
4
4
  enterprise_data/constants.py,sha256=uCKjfpdlMYFZJsAj3n9RMw4Cmg5_6s3NuwocO-fch3s,238
5
5
  enterprise_data/filters.py,sha256=D2EiK12MMpBoz6eOUmTpoJEhj_sH7bA93NRRAdvkDVo,6163
6
- enterprise_data/models.py,sha256=6_rtrxVX-eW7IjJLLFDK712ih-tFqHWzlsPwwTk7XL0,26555
6
+ enterprise_data/models.py,sha256=gbZl-ei0qe_l-BFeE0gWeyfWqmgi9X9LAF8MYOEfk2s,26555
7
7
  enterprise_data/paginators.py,sha256=YPrC5TeXFt-ymenT2H8H2nCbDCnAzJQlH9kFPElRxWE,269
8
- enterprise_data/renderers.py,sha256=qggCLZklL9ohVcLHLO1pSecPJSDCCR7e_-PVobl9Lj8,3063
8
+ enterprise_data/renderers.py,sha256=56cbh7Af49VwHnbyanmtxHHoUc1IFn_U33gkA5V6_k8,3073
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=djGuQUnvT8HJMMV60CzcD5BWerPIwiK9uG26bhkpWMg,3518
@@ -30,7 +30,7 @@ enterprise_data/api/v0/serializers.py,sha256=dngZTk6DhRxApchQKCMp1B_c8aVnQtH0NCq
30
30
  enterprise_data/api/v0/urls.py,sha256=vzJjqIo_S3AXWs9Us8XTaJc3FnxLbYzAkmLyuDQqum0,699
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
- enterprise_data/api/v1/serializers.py,sha256=DUhk8cP-JFQmbLR_JNGmmwis9Un5dyvd01kRdmxn8Lk,11866
33
+ enterprise_data/api/v1/serializers.py,sha256=27LcGcIJPPVm4PedHdgQclrPpdKhtd3E0OJYf4u5sBU,13788
34
34
  enterprise_data/api/v1/urls.py,sha256=Wl1xLboPg-Lq1ZvjAWf51JKYkHlmx02Kpq1nwfDyS8s,4372
35
35
  enterprise_data/api/v1/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  enterprise_data/api/v1/views/analytics_completions.py,sha256=esFbJ5q8ssnm2Mfbc3rZXtiGHF-MeM4KQ4Ft3N7wwHU,6260
@@ -107,6 +107,7 @@ enterprise_data/migrations/0044_enterpriseexecedlcmoduleperformance.py,sha256=1a
107
107
  enterprise_data/migrations/0045_alter_enterpriseexecedlcmoduleperformance_options_and_more.py,sha256=HJkY2OvuE39ciWgaEescd--ixQhTVrwzbL0_bvNofSo,876
108
108
  enterprise_data/migrations/0046_enterprisegroupmembership.py,sha256=38qfi3EySDLrpP3gDuO_oUl_7rphGPZIrPsCuBhQ_dk,1766
109
109
  enterprise_data/migrations/0047_enterpriseexecedlcmoduleperformance_avg_after_lo_score_and_more.py,sha256=_lHmsJozjV_JEWyUfHDKleOhd53594fOaRhz7M0z-nY,897
110
+ enterprise_data/migrations/0048_alter_enterpriseexecedlcmoduleperformance_avg_after_lo_score_and_more.py,sha256=Hjgjj1LwNSCno45EHECCBy5jKKb51Me61xo8ukQLIEI,740
110
111
  enterprise_data/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
112
  enterprise_data/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
113
  enterprise_data/settings/test.py,sha256=4-flfrlf81AthGx9wTaT5PscyoOWyhsDDqbzBl-z7Eg,4191
@@ -174,8 +175,8 @@ enterprise_reporting/tests/test_send_enterprise_reports.py,sha256=zBj7sDvRLJQbRs
174
175
  enterprise_reporting/tests/test_utils.py,sha256=y4t6w9aKra-ftqtUeHvPwOhje-1npz7auV5o74ya8fE,9523
175
176
  enterprise_reporting/tests/test_vertica_client.py,sha256=-R2yNCGUjRtoXwLMBloVFQkFYrJoo613VCr61gwI3kQ,140
176
177
  enterprise_reporting/tests/utils.py,sha256=xms2LM7DV3wczXEfctOK1ddel1EE0J_YSr17UzbCDy4,1401
177
- edx_enterprise_data-10.9.0.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
178
- edx_enterprise_data-10.9.0.dist-info/METADATA,sha256=_5k-MwdCDP9ndzXEVibqx9RoyDVUHwaaDEariCZK2j8,1684
179
- edx_enterprise_data-10.9.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
180
- edx_enterprise_data-10.9.0.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
181
- edx_enterprise_data-10.9.0.dist-info/RECORD,,
178
+ edx_enterprise_data-10.9.2.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
179
+ edx_enterprise_data-10.9.2.dist-info/METADATA,sha256=POBhGmJwAD5O1bHRURgDSxzF7nJ2iOok3jI4MW6BAM0,1684
180
+ edx_enterprise_data-10.9.2.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
181
+ edx_enterprise_data-10.9.2.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
182
+ edx_enterprise_data-10.9.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (76.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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__ = "10.9.0"
5
+ __version__ = "10.9.2"
@@ -6,6 +6,7 @@ from uuid import UUID
6
6
  from rest_framework import serializers
7
7
 
8
8
  from enterprise_data.admin_analytics.constants import ResponseType
9
+ from enterprise_data.cache.decorators import cache_it
9
10
  from enterprise_data.models import (
10
11
  EnterpriseAdminLearnerProgress,
11
12
  EnterpriseAdminSummarizeInsights,
@@ -26,6 +27,8 @@ class EnterpriseLearnerEnrollmentSerializer(serializers.ModelSerializer):
26
27
  course_api_url = serializers.SerializerMethodField()
27
28
  enterprise_user_id = serializers.SerializerMethodField()
28
29
  total_learning_time_hours = serializers.SerializerMethodField()
30
+ enterprise_flex_group_name = serializers.SerializerMethodField()
31
+ enterprise_flex_group_uuid = serializers.SerializerMethodField()
29
32
 
30
33
  class Meta:
31
34
  model = EnterpriseLearnerEnrollment
@@ -44,8 +47,9 @@ class EnterpriseLearnerEnrollmentSerializer(serializers.ModelSerializer):
44
47
  'last_activity_date', 'progress_status', 'passed_date', 'current_grade',
45
48
  'letter_grade', 'enterprise_user_id', 'user_email', 'user_account_creation_date',
46
49
  'user_country_code', 'user_username', 'user_first_name', 'user_last_name', 'enterprise_name',
47
- 'enterprise_customer_uuid', 'enterprise_sso_uid', 'created', 'course_api_url', 'total_learning_time_hours',
48
- 'is_subsidy', 'course_product_line', 'budget_id', 'enterprise_group_name', 'enterprise_group_uuid',
50
+ 'enterprise_customer_uuid', 'enterprise_sso_uid', 'created', 'course_api_url',
51
+ 'total_learning_time_hours', 'is_subsidy', 'course_product_line', 'budget_id',
52
+ 'enterprise_flex_group_name', 'enterprise_flex_group_uuid',
49
53
  )
50
54
 
51
55
  def get_course_api_url(self, obj):
@@ -62,6 +66,51 @@ class EnterpriseLearnerEnrollmentSerializer(serializers.ModelSerializer):
62
66
  """Returns the learners total learning time in hours"""
63
67
  return round((obj.total_learning_time_seconds or 0.0)/3600.0, 2)
64
68
 
69
+ @cache_it()
70
+ def _get_flex_groups(self, obj):
71
+ """
72
+ Returns list of tuples containing group (name, uuid) pairs for the learner.
73
+ This is cached to prevent duplicate database queries.
74
+ """
75
+ enterprise_user_id = obj.enterprise_user_id
76
+
77
+ if not enterprise_user_id:
78
+ return []
79
+
80
+ # Get all group memberships for this user in a single query
81
+ # Order by name for consistent ordering
82
+ return list(
83
+ EnterpriseGroupMembership.objects.filter(
84
+ enterprise_customer_user_id=enterprise_user_id,
85
+ membership_is_removed=False,
86
+ group_is_removed=False,
87
+ group_type="flex",
88
+ )
89
+ .order_by("enterprise_group_name")
90
+ .values_list("enterprise_group_name", "enterprise_group_uuid")
91
+ .distinct()
92
+ )
93
+
94
+ def get_enterprise_flex_group_name(self, obj):
95
+ """Returns a comma-separated list of enterprise group names that the learner is associated with"""
96
+ groups = self._get_flex_groups(obj)
97
+
98
+ if not groups:
99
+ return obj.enterprise_group_name
100
+
101
+ # Return comma-separated list of group names (first element of each tuple)
102
+ return ', '.join(group[0] for group in groups)
103
+
104
+ def get_enterprise_flex_group_uuid(self, obj):
105
+ """Returns a comma-separated list of enterprise group UUIDs that the learner is associated with"""
106
+ groups = self._get_flex_groups(obj)
107
+
108
+ if not groups:
109
+ return obj.enterprise_group_uuid
110
+
111
+ # Return comma-separated list of group UUIDs (second element of each tuple)
112
+ return ', '.join(str(group[1]) for group in groups)
113
+
65
114
 
66
115
  class EnterpriseSubsidyBudgetSerializer(serializers.ModelSerializer):
67
116
  """
@@ -0,0 +1,23 @@
1
+ # Generated by Django 4.2.15 on 2025-02-25 08:17
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('enterprise_data', '0047_enterpriseexecedlcmoduleperformance_avg_after_lo_score_and_more'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name='enterpriseexecedlcmoduleperformance',
15
+ name='avg_after_lo_score',
16
+ field=models.DecimalField(decimal_places=2, max_digits=38, null=True),
17
+ ),
18
+ migrations.AlterField(
19
+ model_name='enterpriseexecedlcmoduleperformance',
20
+ name='avg_before_lo_score',
21
+ field=models.DecimalField(decimal_places=2, max_digits=38, null=True),
22
+ ),
23
+ ]
enterprise_data/models.py CHANGED
@@ -559,8 +559,8 @@ class EnterpriseExecEdLCModulePerformance(models.Model):
559
559
  discussion_forum_activities_total_count = models.PositiveIntegerField(null=True)
560
560
  pass_grade = models.DecimalField(max_digits=38, decimal_places=2, null=True)
561
561
  question_name = models.CharField(max_length=500, null=True)
562
- avg_before_lo_score = models.DecimalField(max_digits=38, decimal_places=6, null=True)
563
- avg_after_lo_score = models.DecimalField(max_digits=38, decimal_places=6, null=True)
562
+ avg_before_lo_score = models.DecimalField(max_digits=38, decimal_places=2, null=True)
563
+ avg_after_lo_score = models.DecimalField(max_digits=38, decimal_places=2, null=True)
564
564
 
565
565
  def __str__(self):
566
566
  """
@@ -27,7 +27,7 @@ class EnrollmentsCSVRenderer(CSVStreamingRenderer):
27
27
  'letter_grade', 'enterprise_user_id', 'user_email', 'user_account_creation_date',
28
28
  'user_country_code', 'user_username', 'user_first_name', 'user_last_name', 'enterprise_name',
29
29
  'enterprise_customer_uuid', 'enterprise_sso_uid', 'created', 'course_api_url', 'total_learning_time_hours',
30
- 'is_subsidy', 'course_product_line', 'budget_id', 'enterprise_group_name', 'enterprise_group_uuid',
30
+ 'is_subsidy', 'course_product_line', 'budget_id', 'enterprise_flex_group_name', 'enterprise_flex_group_uuid',
31
31
  ]
32
32
 
33
33