edx-enterprise-data 8.4.0__py3-none-any.whl → 8.5.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: 8.4.0
3
+ Version: 8.5.0
4
4
  Summary: Enterprise Reporting
5
5
  Home-page: https://github.com/openedx/edx-enterprise-data
6
6
  Author: edX
@@ -1,9 +1,9 @@
1
- enterprise_data/__init__.py,sha256=V3f8VWSTHKMmk7VgKNYsFMadFosPMVNgWxHub9YqP9c,123
1
+ enterprise_data/__init__.py,sha256=93nSn1NykQTFtU7czMTFJab_r7CaAtL_iv-q3peH5ME,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
5
5
  enterprise_data/filters.py,sha256=D2EiK12MMpBoz6eOUmTpoJEhj_sH7bA93NRRAdvkDVo,6163
6
- enterprise_data/models.py,sha256=3VHJ5eWfI0KZxh5u969E7uA2nE5VZqyUnk_VV--UTI4,19154
6
+ enterprise_data/models.py,sha256=khGcOh7NWP8KGu84t78Y2zAu3knREeXA_prApmU2NX8,24428
7
7
  enterprise_data/paginators.py,sha256=YPrC5TeXFt-ymenT2H8H2nCbDCnAzJQlH9kFPElRxWE,269
8
8
  enterprise_data/renderers.py,sha256=WVt0qy9Ippdnl404Zsq-MruB9oQfY6h87ZzpScYBeaw,1770
9
9
  enterprise_data/signals.py,sha256=8eqNPnlvmfsKf19lGWv5xTIuBgQIqR8EZSp9UYzC8Rc,1024
@@ -20,11 +20,11 @@ enterprise_data/api/v0/serializers.py,sha256=dngZTk6DhRxApchQKCMp1B_c8aVnQtH0NCq
20
20
  enterprise_data/api/v0/urls.py,sha256=vzJjqIo_S3AXWs9Us8XTaJc3FnxLbYzAkmLyuDQqum0,699
21
21
  enterprise_data/api/v0/views.py,sha256=4RslZ4NZOU-844bnebEQ71ji2utRY7jEijqC45oQQD0,14380
22
22
  enterprise_data/api/v1/__init__.py,sha256=1aAzAYU5hk-RW6cKUxa1645cbZMxn7GIZ7OMjWc9MKI,46
23
- enterprise_data/api/v1/serializers.py,sha256=AOHumabnzwK59nytoOZEWhA3f9EL_CV-bXPsYSH3LI8,8263
24
- enterprise_data/api/v1/urls.py,sha256=m5B01cZuInVsJkRdUloHC45fHxSJKQMSzBSCgU2GpkA,1855
23
+ enterprise_data/api/v1/serializers.py,sha256=5C7IYNUuW7HvFVqtbsLIBE6A2Ywzmy6SFzPc4FjtclY,8562
24
+ enterprise_data/api/v1/urls.py,sha256=OlchBMQmyvhM2HpVbbSZCMpUD_y8tP9-vsorGtBvxVo,2048
25
25
  enterprise_data/api/v1/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  enterprise_data/api/v1/views/base.py,sha256=FTAxlz5EzvAY657wzVgzhJPFSCHHzct7IDcvm71Smt8,866
27
- enterprise_data/api/v1/views/enterprise_admin.py,sha256=hBUj5XPyyBwpyNED62lLlV1etRK9vHRS6aYnZLTF2w0,8081
27
+ enterprise_data/api/v1/views/enterprise_admin.py,sha256=RTSRyPfHvbzV_ihSbGjYi0VuE6AjaYZIyqpAKTMYa5Q,8980
28
28
  enterprise_data/api/v1/views/enterprise_learner.py,sha256=yABjJje3CT8I8YOhWr1_tTkdKtnGJom8eu3EFz_-0BU,18517
29
29
  enterprise_data/api/v1/views/enterprise_offers.py,sha256=VifxgqTLFLVw4extYPlHcN1N_yjXcsYsAlYEnAbpb10,1266
30
30
  enterprise_data/fixtures/enterprise_enrollment.json,sha256=6onPXXR29pMdTdbl_mn81sDi3Re5jkLUZz2TPMB_1IY,5786
@@ -85,6 +85,7 @@ enterprise_data/migrations/0037_alter_enterpriseenrollment_consent_granted.py,sh
85
85
  enterprise_data/migrations/0038_enterpriseoffer_export_timestamp.py,sha256=8St3DsKb-VI3LGGC-Mc7OvmFn67kVob0HKCPGKcjvu4,436
86
86
  enterprise_data/migrations/0039_auto_20240212_1403.py,sha256=rMiJcYx26ZGqPdQzgiWkUgbcRhD-tp9BgXdgt67vC2Q,1002
87
87
  enterprise_data/migrations/0040_auto_20240718_0536_squashed_0043_alter_enterpriselearnerenrollment_enterprise_enrollment_id.py,sha256=Kq_ResqoAsJjtyIysHjs4VaDxNh6p4fPMMyh93GIJxA,1693
88
+ enterprise_data/migrations/0044_enterpriseexecedlcmoduleperformance.py,sha256=1aJ0wIu9K2cT3AJdBIHuNCUpJysPWmq_37Ucp5ntEO8,6122
88
89
  enterprise_data/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
89
90
  enterprise_data/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
91
  enterprise_data/settings/test.py,sha256=4-flfrlf81AthGx9wTaT5PscyoOWyhsDDqbzBl-z7Eg,4191
@@ -147,8 +148,8 @@ enterprise_reporting/tests/test_send_enterprise_reports.py,sha256=WtL-RqGgu2x5PP
147
148
  enterprise_reporting/tests/test_utils.py,sha256=Zt_TA0LVb-B6fQGkUkAKKVlUKKnQh8jnw1US1jKe7g8,9493
148
149
  enterprise_reporting/tests/test_vertica_client.py,sha256=-R2yNCGUjRtoXwLMBloVFQkFYrJoo613VCr61gwI3kQ,140
149
150
  enterprise_reporting/tests/utils.py,sha256=xms2LM7DV3wczXEfctOK1ddel1EE0J_YSr17UzbCDy4,1401
150
- edx_enterprise_data-8.4.0.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
151
- edx_enterprise_data-8.4.0.dist-info/METADATA,sha256=o0b8zqSTviYu9WVM9aDEK6ozyC_PBJlKxUQJC3fNZic,1569
152
- edx_enterprise_data-8.4.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
153
- edx_enterprise_data-8.4.0.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
154
- edx_enterprise_data-8.4.0.dist-info/RECORD,,
151
+ edx_enterprise_data-8.5.0.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
152
+ edx_enterprise_data-8.5.0.dist-info/METADATA,sha256=oabxLQt9xaTLpOgQX1KdSryfXehxEHBMEroSMHcU6-I,1569
153
+ edx_enterprise_data-8.5.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
154
+ edx_enterprise_data-8.5.0.dist-info/top_level.txt,sha256=f5F2kU-dob6MqiHJpgZkFzoCD5VMhsdpkTV5n9Tvq3I,59
155
+ edx_enterprise_data-8.5.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.4.0"
5
+ __version__ = "8.5.0"
@@ -8,6 +8,7 @@ from rest_framework import serializers
8
8
  from enterprise_data.models import (
9
9
  EnterpriseAdminLearnerProgress,
10
10
  EnterpriseAdminSummarizeInsights,
11
+ EnterpriseExecEdLCModulePerformance,
11
12
  EnterpriseLearner,
12
13
  EnterpriseLearnerEnrollment,
13
14
  EnterpriseOffer,
@@ -216,3 +217,13 @@ class AdminAnalyticsAggregatesQueryParamsSerializer(serializers.Serializer): #
216
217
  if attrs['start_date'] > attrs['end_date']:
217
218
  raise serializers.ValidationError("start_date should be less than or equal to end_date.")
218
219
  return attrs
220
+
221
+
222
+ class EnterpriseExecEdLCModulePerformanceSerializer(serializers.ModelSerializer):
223
+ """
224
+ Serializer for EnterpriseExecEdLCModulePerformance model.
225
+ """
226
+
227
+ class Meta:
228
+ model = EnterpriseExecEdLCModulePerformance
229
+ fields = '__all__'
@@ -35,6 +35,11 @@ router.register(
35
35
  enterprise_learner_views.EnterpriseLearnerCompletedCoursesViewSet,
36
36
  'enterprise-learner-completed-courses',
37
37
  )
38
+ router.register(
39
+ r'enterprise/(?P<enterprise_id>.+)/module-performance',
40
+ enterprise_admin_views.EnterpriseExecEdLCModulePerformanceViewSet,
41
+ 'enterprise-admin-module-performance',
42
+ )
38
43
 
39
44
  urlpatterns = [
40
45
  re_path(
@@ -1,11 +1,11 @@
1
1
  """
2
2
  Views for enterprise admin api v1.
3
3
  """
4
-
5
4
  from datetime import datetime, timedelta
6
5
 
7
6
  from edx_rbac.decorators import permission_required
8
7
  from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
8
+ from rest_framework import filters, viewsets
9
9
  from rest_framework.response import Response
10
10
  from rest_framework.status import HTTP_200_OK, HTTP_404_NOT_FOUND
11
11
  from rest_framework.views import APIView
@@ -22,9 +22,15 @@ from enterprise_data.admin_analytics.utils import (
22
22
  get_top_skills_csv_data,
23
23
  )
24
24
  from enterprise_data.api.v1 import serializers
25
- from enterprise_data.models import EnterpriseAdminLearnerProgress, EnterpriseAdminSummarizeInsights
25
+ from enterprise_data.models import (
26
+ EnterpriseAdminLearnerProgress,
27
+ EnterpriseAdminSummarizeInsights,
28
+ EnterpriseExecEdLCModulePerformance,
29
+ )
26
30
  from enterprise_data.utils import date_filter
27
31
 
32
+ from .base import EnterpriseViewSetMixin
33
+
28
34
 
29
35
  class EnterpriseAdminInsightsView(APIView):
30
36
  """
@@ -109,16 +115,16 @@ class EnterpriseAdminAnalyticsAggregatesView(APIView):
109
115
  # 1. minimum enrollment date from the data as the start_date
110
116
  # 2. today's date as the end_date
111
117
  start_date = serializer.data.get(
112
- "start_date", enrollment.enterprise_enrollment_date.min()
118
+ 'start_date', enrollment.enterprise_enrollment_date.min()
113
119
  )
114
- end_date = serializer.data.get("end_date", datetime.now())
120
+ end_date = serializer.data.get('end_date', datetime.now())
115
121
 
116
122
  # Date filtering.
117
123
  dff = date_filter(
118
124
  start=start_date,
119
125
  end=end_date,
120
126
  data_frame=enrollment.copy(),
121
- date_column="enterprise_enrollment_date",
127
+ date_column='enterprise_enrollment_date',
122
128
  )
123
129
 
124
130
  enrolls = len(dff)
@@ -128,7 +134,7 @@ class EnterpriseAdminAnalyticsAggregatesView(APIView):
128
134
  start=start_date,
129
135
  end=end_date,
130
136
  data_frame=enrollment.copy(),
131
- date_column="passed_date",
137
+ date_column='passed_date',
132
138
  )
133
139
 
134
140
  completions = dff.has_passed.sum()
@@ -138,7 +144,7 @@ class EnterpriseAdminAnalyticsAggregatesView(APIView):
138
144
  start=start_date,
139
145
  end=end_date,
140
146
  data_frame=engagement.copy(),
141
- date_column="activity_date",
147
+ date_column='activity_date',
142
148
  )
143
149
 
144
150
  hours = round(dff.learning_time_seconds.sum() / 60 / 60, 1)
@@ -146,14 +152,14 @@ class EnterpriseAdminAnalyticsAggregatesView(APIView):
146
152
 
147
153
  return Response(
148
154
  data={
149
- "enrolls": enrolls,
150
- "courses": courses,
151
- "completions": completions,
152
- "hours": hours,
153
- "sessions": sessions,
154
- "last_updated_at": last_updated_at.date() if last_updated_at else None,
155
- "min_enrollment_date": enrollment.enterprise_enrollment_date.min().date(),
156
- "max_enrollment_date": enrollment.enterprise_enrollment_date.max().date(),
155
+ 'enrolls': enrolls,
156
+ 'courses': courses,
157
+ 'completions': completions,
158
+ 'hours': hours,
159
+ 'sessions': sessions,
160
+ 'last_updated_at': last_updated_at.date() if last_updated_at else None,
161
+ 'min_enrollment_date': enrollment.enterprise_enrollment_date.min().date(),
162
+ 'max_enrollment_date': enrollment.enterprise_enrollment_date.max().date(),
157
163
  },
158
164
  status=HTTP_200_OK,
159
165
  )
@@ -231,3 +237,25 @@ class EnterpriseAdminAnalyticsSkillsView(APIView):
231
237
  }
232
238
 
233
239
  return Response(data=response_data, status=HTTP_200_OK)
240
+
241
+
242
+ class EnterpriseExecEdLCModulePerformanceViewSet(EnterpriseViewSetMixin, viewsets.ReadOnlyModelViewSet):
243
+ """
244
+ View to for getting enterprise exec ed learner module performance records.
245
+ """
246
+ serializer_class = serializers.EnterpriseExecEdLCModulePerformanceSerializer
247
+ filter_backends = (filters.OrderingFilter, filters.SearchFilter)
248
+ ordering_fields = '__all__'
249
+ ordering = ('last_access',)
250
+ search_fields = (
251
+ 'username',
252
+ 'course_name'
253
+ )
254
+
255
+ def get_queryset(self):
256
+ """
257
+ Return the queryset of EnterpriseExecEdLCModulePerformance objects.
258
+ """
259
+ return EnterpriseExecEdLCModulePerformance.objects.filter(
260
+ enterprise_customer_uuid=self.kwargs['enterprise_id'],
261
+ )
@@ -0,0 +1,87 @@
1
+ # Generated by Django 4.2.14 on 2024-08-08 07:43
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('enterprise_data', '0040_auto_20240718_0536_squashed_0043_alter_enterpriselearnerenrollment_enterprise_enrollment_id'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.CreateModel(
14
+ name='EnterpriseExecEdLCModulePerformance',
15
+ fields=[
16
+ ('module_performance_unique_id', models.CharField(max_length=350, primary_key=True, serialize=False)),
17
+ ('registration_id', models.PositiveIntegerField(null=True)),
18
+ ('subsidy_transaction_id', models.UUIDField(null=True)),
19
+ ('enterprise_customer_uuid', models.UUIDField(db_index=True, null=True)),
20
+ ('ocm_lms_user_id', models.PositiveIntegerField(null=True)),
21
+ ('is_internal_subsidy', models.BooleanField(null=True)),
22
+ ('ocm_enrollment_id', models.PositiveIntegerField(null=True)),
23
+ ('ocm_courserun_key', models.CharField(max_length=255, null=True)),
24
+ ('university_name', models.CharField(max_length=500, null=True)),
25
+ ('university_abbreviation', models.CharField(max_length=255, null=True)),
26
+ ('partner_short_name', models.CharField(max_length=255, null=True)),
27
+ ('university_country', models.CharField(max_length=255, null=True)),
28
+ ('school', models.CharField(max_length=500, null=True)),
29
+ ('faculty', models.CharField(max_length=500, null=True)),
30
+ ('department', models.CharField(max_length=500, null=True)),
31
+ ('course_code', models.PositiveIntegerField(null=True)),
32
+ ('course_name', models.CharField(db_index=True, max_length=500)),
33
+ ('course_abbreviation', models.CharField(max_length=128, null=True)),
34
+ ('course_abbreviation_short', models.CharField(max_length=64, null=True)),
35
+ ('course_type', models.CharField(max_length=128, null=True)),
36
+ ('subject_vertical', models.CharField(max_length=128, null=True)),
37
+ ('presentation_abbreviation', models.CharField(max_length=128, null=True)),
38
+ ('presentation_name', models.CharField(max_length=500, null=True)),
39
+ ('presentation_code', models.PositiveIntegerField(null=True)),
40
+ ('presentation_close_date', models.DateField(null=True)),
41
+ ('presentation_start_date', models.DateField(null=True)),
42
+ ('promotion_code', models.CharField(max_length=255, null=True)),
43
+ ('promotion_category_name', models.CharField(max_length=255, null=True)),
44
+ ('product_type', models.CharField(max_length=128, null=True)),
45
+ ('product_life_cycle_status', models.CharField(max_length=128, null=True)),
46
+ ('enrolment_id', models.PositiveIntegerField(null=True)),
47
+ ('olc_user_id', models.PositiveIntegerField(null=True)),
48
+ ('first_name', models.CharField(max_length=255, null=True)),
49
+ ('last_name', models.CharField(max_length=255, null=True)),
50
+ ('username', models.CharField(db_index=True, max_length=255)),
51
+ ('status', models.CharField(max_length=128, null=True)),
52
+ ('company_name', models.CharField(max_length=255, null=True)),
53
+ ('module_number', models.PositiveIntegerField(null=True)),
54
+ ('module_name', models.CharField(max_length=255, null=True)),
55
+ ('module_1_release_date', models.DateField(null=True)),
56
+ ('last_module_release_date', models.DateField(null=True)),
57
+ ('last_module_end_date', models.DateField(null=True)),
58
+ ('final_mark', models.DecimalField(decimal_places=2, max_digits=38, null=True)),
59
+ ('assign_grade', models.DecimalField(decimal_places=2, max_digits=38, null=True)),
60
+ ('last_access', models.DateField(null=True)),
61
+ ('all_activities_completed_count', models.PositiveIntegerField(null=True)),
62
+ ('all_activities_total_count', models.PositiveIntegerField(null=True)),
63
+ ('percentage_completed_activities', models.DecimalField(decimal_places=2, max_digits=38, null=True)),
64
+ ('extensions_requested', models.PositiveIntegerField(null=True)),
65
+ ('module_grade', models.DecimalField(decimal_places=2, max_digits=38, null=True)),
66
+ ('log_viewed', models.PositiveIntegerField(null=True)),
67
+ ('hours_online', models.DecimalField(decimal_places=2, max_digits=38, null=True)),
68
+ ('orientation_module_accessed', models.CharField(max_length=128, null=True)),
69
+ ('graded_activities_completed_count', models.PositiveIntegerField(null=True)),
70
+ ('graded_activities_total_count', models.PositiveIntegerField(null=True)),
71
+ ('percentage_completed_graded_activities', models.DecimalField(decimal_places=2, max_digits=38, null=True)),
72
+ ('assessment_activities_completed_count', models.PositiveIntegerField(null=True)),
73
+ ('assessment_activities_total_count', models.PositiveIntegerField(null=True)),
74
+ ('course_material_activities_completed_count', models.PositiveIntegerField(null=True)),
75
+ ('course_material_activities_total_count', models.PositiveIntegerField(null=True)),
76
+ ('discussion_forum_activities_completed_count', models.PositiveIntegerField(null=True)),
77
+ ('discussion_forum_activities_total_count', models.PositiveIntegerField(null=True)),
78
+ ('pass_grade', models.DecimalField(decimal_places=2, max_digits=38, null=True)),
79
+ ],
80
+ options={
81
+ 'verbose_name': 'Exec Ed LC Module Performance',
82
+ 'verbose_name_plural': 'Exec Ed LC Module Performance',
83
+ 'db_table': 'exec_ed_lc_module_performance',
84
+ 'ordering': ['last_access'],
85
+ },
86
+ ),
87
+ ]
enterprise_data/models.py CHANGED
@@ -434,3 +434,97 @@ class EnterpriseUser(models.Model):
434
434
  Return uniquely identifying string representation.
435
435
  """
436
436
  return self.__str__()
437
+
438
+
439
+ class EnterpriseExecEdLCModulePerformance(models.Model):
440
+ """
441
+ Model for Exec Ed LC Module Performance.
442
+ """
443
+
444
+ objects = EnterpriseReportingModelManager()
445
+
446
+ class Meta:
447
+ app_label = 'enterprise_data'
448
+ db_table = 'exec_ed_lc_module_performance'
449
+ verbose_name = _("Exec Ed LC Module Performance")
450
+ verbose_name_plural = _("Exec Ed LC Module Performance")
451
+
452
+ module_performance_unique_id = models.CharField(max_length=350, primary_key=True)
453
+ registration_id = models.PositiveIntegerField(null=True)
454
+ subsidy_transaction_id = models.UUIDField(null=True)
455
+ enterprise_customer_uuid = models.UUIDField(db_index=True, null=True)
456
+ ocm_lms_user_id = models.PositiveIntegerField(null=True)
457
+ is_internal_subsidy = models.BooleanField(null=True)
458
+ ocm_enrollment_id = models.PositiveIntegerField(null=True)
459
+ ocm_courserun_key = models.CharField(max_length=255, null=True)
460
+ university_name = models.CharField(max_length=500, null=True)
461
+ university_abbreviation = models.CharField(max_length=255, null=True)
462
+ partner_short_name = models.CharField(max_length=255, null=True)
463
+ university_country = models.CharField(max_length=255, null=True)
464
+ school = models.CharField(max_length=500, null=True)
465
+ faculty = models.CharField(max_length=500, null=True)
466
+ department = models.CharField(max_length=500, null=True)
467
+ course_code = models.PositiveIntegerField(null=True)
468
+ course_name = models.CharField(max_length=500, db_index=True)
469
+ course_abbreviation = models.CharField(max_length=128, null=True)
470
+ course_abbreviation_short = models.CharField(max_length=64, null=True)
471
+ course_type = models.CharField(max_length=128, null=True)
472
+ subject_vertical = models.CharField(max_length=128, null=True)
473
+ presentation_abbreviation = models.CharField(max_length=128, null=True)
474
+ presentation_name = models.CharField(max_length=500, null=True)
475
+ presentation_code = models.PositiveIntegerField(null=True)
476
+ presentation_close_date = models.DateField(null=True)
477
+ presentation_start_date = models.DateField(null=True)
478
+ promotion_code = models.CharField(max_length=255, null=True)
479
+ promotion_category_name = models.CharField(max_length=255, null=True)
480
+ product_type = models.CharField(max_length=128, null=True)
481
+ product_life_cycle_status = models.CharField(max_length=128, null=True)
482
+ enrolment_id = models.PositiveIntegerField(null=True)
483
+ olc_user_id = models.PositiveIntegerField(null=True)
484
+ first_name = models.CharField(max_length=255, null=True)
485
+ last_name = models.CharField(max_length=255, null=True)
486
+ username = models.CharField(max_length=255, db_index=True)
487
+ status = models.CharField(max_length=128, null=True)
488
+ company_name = models.CharField(max_length=255, null=True)
489
+ module_number = models.PositiveIntegerField(null=True)
490
+ module_name = models.CharField(max_length=255, null=True)
491
+ module_1_release_date = models.DateField(null=True)
492
+ last_module_release_date = models.DateField(null=True)
493
+ last_module_end_date = models.DateField(null=True)
494
+ final_mark = models.DecimalField(max_digits=38, decimal_places=2, null=True)
495
+ assign_grade = models.DecimalField(max_digits=38, decimal_places=2, null=True)
496
+ last_access = models.DateField(null=True)
497
+ all_activities_completed_count = models.PositiveIntegerField(null=True)
498
+ all_activities_total_count = models.PositiveIntegerField(null=True)
499
+ percentage_completed_activities = models.DecimalField(max_digits=38, decimal_places=2, null=True)
500
+ extensions_requested = models.PositiveIntegerField(null=True)
501
+ module_grade = models.DecimalField(max_digits=38, decimal_places=2, null=True)
502
+ log_viewed = models.PositiveIntegerField(null=True)
503
+ hours_online = models.DecimalField(max_digits=38, decimal_places=2, null=True)
504
+ orientation_module_accessed = models.CharField(max_length=128, null=True)
505
+ graded_activities_completed_count = models.PositiveIntegerField(null=True)
506
+ graded_activities_total_count = models.PositiveIntegerField(null=True)
507
+ percentage_completed_graded_activities = models.DecimalField(max_digits=38, decimal_places=2, null=True)
508
+ assessment_activities_completed_count = models.PositiveIntegerField(null=True)
509
+ assessment_activities_total_count = models.PositiveIntegerField(null=True)
510
+ course_material_activities_completed_count = models.PositiveIntegerField(null=True)
511
+ course_material_activities_total_count = models.PositiveIntegerField(null=True)
512
+ discussion_forum_activities_completed_count = models.PositiveIntegerField(null=True)
513
+ discussion_forum_activities_total_count = models.PositiveIntegerField(null=True)
514
+ pass_grade = models.DecimalField(max_digits=38, decimal_places=2, null=True)
515
+
516
+ def __str__(self):
517
+ """
518
+ Return a human-readable string representation of the object.
519
+ """
520
+ return "<EnterpriseExecEdLCModulePerformance User {user} of {enterprise} in module {module}>".format(
521
+ user=self.ocm_lms_user_id,
522
+ enterprise=self.enterprise_customer_uuid,
523
+ module=self.module_number,
524
+ )
525
+
526
+ def __repr__(self):
527
+ """
528
+ Return uniquely identifying string representation.
529
+ """
530
+ return self.__str__()