Skip to content

Commit

Permalink
feat: updated apps config and added migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
sameeramin committed Dec 27, 2024
1 parent 88374a0 commit 2e91618
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 49 deletions.
13 changes: 0 additions & 13 deletions channel_integrations/apps.py

This file was deleted.

1 change: 1 addition & 0 deletions channel_integrations/integrated_channel/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ class IntegratedChannelConfig(AppConfig):
"""
name = 'channel_integrations.integrated_channel'
verbose_name = "Enterprise Integrated Channels"
label = 'channel_integration'
151 changes: 151 additions & 0 deletions channel_integrations/integrated_channel/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Generated by Django 4.2.17 on 2024-12-27 06:17

from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import jsonfield.fields
import model_utils.fields


class Migration(migrations.Migration):

initial = True

dependencies = [
('enterprise', '0228_alter_defaultenterpriseenrollmentrealization_realized_enrollment'),
]

operations = [
migrations.CreateModel(
name='ApiResponseRecord',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('status_code', models.PositiveIntegerField(blank=True, help_text='The most recent remote API call response HTTP status code', null=True)),
('body', models.TextField(blank=True, help_text='The most recent remote API call response body', null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='ContentMetadataItemTransmission',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('integrated_channel_code', models.CharField(max_length=30)),
('plugin_configuration_id', models.PositiveIntegerField(blank=True, null=True)),
('content_id', models.CharField(max_length=255)),
('content_title', models.CharField(blank=True, default=None, max_length=255, null=True)),
('channel_metadata', jsonfield.fields.JSONField()),
('content_last_changed', models.DateTimeField(blank=True, help_text='Date of the last time the enterprise catalog associated with this metadata item was updated', null=True)),
('enterprise_customer_catalog_uuid', models.UUIDField(blank=True, help_text='The enterprise catalog that this metadata item was derived from', null=True)),
('remote_deleted_at', models.DateTimeField(blank=True, help_text='Date when the content transmission was deleted in the remote API', null=True)),
('remote_created_at', models.DateTimeField(blank=True, help_text='Date when the content transmission was created in the remote API', null=True)),
('remote_errored_at', models.DateTimeField(blank=True, help_text='Date when the content transmission was failed in the remote API.', null=True)),
('remote_updated_at', models.DateTimeField(blank=True, help_text='Date when the content transmission was last updated in the remote API', null=True)),
('api_response_status_code', models.PositiveIntegerField(blank=True, help_text='The most recent remote API call response HTTP status code', null=True)),
('friendly_status_message', models.CharField(blank=True, default=None, help_text='A user-friendly API response status message.', max_length=255, null=True)),
('marked_for', models.CharField(blank=True, help_text='Flag marking a record as needing a form of transmitting', max_length=32, null=True)),
('api_record', models.OneToOneField(blank=True, help_text='Data pertaining to the transmissions API request response.', null=True, on_delete=django.db.models.deletion.CASCADE, to='channel_integration.apiresponserecord')),
('enterprise_customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='channelintegration_contentmetadataitemtransmission', to='enterprise.enterprisecustomer')),
],
options={
'unique_together': {('integrated_channel_code', 'plugin_configuration_id', 'content_id')},
'index_together': {('enterprise_customer', 'integrated_channel_code', 'plugin_configuration_id', 'content_id')},
},
),
migrations.CreateModel(
name='IntegratedChannelAPIRequestLogs',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('enterprise_customer_configuration_id', models.IntegerField(help_text='ID from the EnterpriseCustomerConfiguration model')),
('endpoint', models.URLField(max_length=255)),
('payload', models.TextField()),
('time_taken', models.FloatField()),
('status_code', models.PositiveIntegerField(blank=True, help_text='API call response HTTP status code', null=True)),
('response_body', models.TextField(blank=True, help_text='API call response body', null=True)),
('channel_name', models.TextField(blank=True, help_text='Name of the integrated channel associated with this API call log record.')),
('enterprise_customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='channelintegration_integratedchannelapirequestlogs', to='enterprise.enterprisecustomer')),
],
options={
'verbose_name_plural': 'Integrated channels API request logs',
},
),
migrations.CreateModel(
name='GenericLearnerDataTransmissionAudit',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('enterprise_customer_uuid', models.UUIDField(blank=True, null=True)),
('user_email', models.CharField(blank=True, max_length=255, null=True)),
('plugin_configuration_id', models.IntegerField(blank=True, null=True)),
('enterprise_course_enrollment_id', models.IntegerField(blank=True, db_index=True, null=True)),
('course_id', models.CharField(max_length=255)),
('content_title', models.CharField(blank=True, default=None, max_length=255, null=True)),
('course_completed', models.BooleanField(default=True)),
('progress_status', models.CharField(blank=True, max_length=255)),
('completed_timestamp', models.DateTimeField(blank=True, null=True)),
('instructor_name', models.CharField(blank=True, max_length=255)),
('grade', models.FloatField(blank=True, null=True)),
('total_hours', models.FloatField(blank=True, null=True)),
('subsection_id', models.CharField(blank=True, db_index=True, max_length=255, null=True)),
('subsection_name', models.CharField(max_length=255, null=True)),
('status', models.CharField(blank=True, max_length=100, null=True)),
('error_message', models.TextField(blank=True, null=True)),
('is_transmitted', models.BooleanField(default=False)),
('friendly_status_message', models.CharField(blank=True, default=None, help_text='A user-friendly API response status message.', max_length=255, null=True)),
('api_record', models.OneToOneField(blank=True, help_text='Data pertaining to the transmissions API request response.', null=True, on_delete=django.db.models.deletion.CASCADE, to='channel_integration.apiresponserecord')),
],
),
migrations.CreateModel(
name='GenericEnterpriseCustomerPluginConfiguration',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('deleted_at', models.DateTimeField(blank=True, null=True)),
('display_name', models.CharField(blank=True, default='', help_text='A configuration nickname.', max_length=255)),
('idp_id', models.CharField(blank=True, default='', help_text='If provided, will be used as IDP slug to locate remote id for learners', max_length=255)),
('active', models.BooleanField(help_text='Is this configuration active?')),
('dry_run_mode_enabled', models.BooleanField(default=False, help_text='Is this configuration in dry-run mode? (experimental)')),
('show_course_price', models.BooleanField(default=False, help_text='Displays course price')),
('transmission_chunk_size', models.IntegerField(default=500, help_text='The maximum number of data items to transmit to the integrated channel with each request.')),
('channel_worker_username', models.CharField(blank=True, default='', help_text='Enterprise channel worker username to get JWT tokens for authenticating LMS APIs.', max_length=255)),
('catalogs_to_transmit', models.TextField(blank=True, default='', help_text='A comma-separated list of catalog UUIDs to transmit. If blank, all customer catalogs will be transmitted. If there are overlapping courses in the customer catalogs, the overlapping course metadata will be selected from the newest catalog.')),
('disable_learner_data_transmissions', models.BooleanField(default=False, help_text='When set to True, the configured customer will no longer receive learner data transmissions, both scheduled and signal based', verbose_name='Disable Learner Data Transmission')),
('last_sync_attempted_at', models.DateTimeField(blank=True, help_text='The DateTime of the most recent Content or Learner data record sync attempt', null=True)),
('last_content_sync_attempted_at', models.DateTimeField(blank=True, help_text='The DateTime of the most recent Content data record sync attempt', null=True)),
('last_learner_sync_attempted_at', models.DateTimeField(blank=True, help_text='The DateTime of the most recent Learner data record sync attempt', null=True)),
('last_sync_errored_at', models.DateTimeField(blank=True, help_text='The DateTime of the most recent failure of a Content or Learner data record sync attempt', null=True)),
('last_content_sync_errored_at', models.DateTimeField(blank=True, help_text='The DateTime of the most recent failure of a Content data record sync attempt', null=True)),
('last_learner_sync_errored_at', models.DateTimeField(blank=True, help_text='The DateTime of the most recent failure of a Learner data record sync attempt', null=True)),
('last_modified_at', models.DateTimeField(auto_now=True, help_text='The DateTime of the last change made to this configuration.', null=True)),
('enterprise_customer', models.ForeignKey(help_text='Enterprise Customer associated with the configuration.', on_delete=django.db.models.deletion.CASCADE, related_name='channelintegration_enterprisecustomerpluginconfiguration', to='enterprise.enterprisecustomer')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='OrphanedContentTransmissions',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('integrated_channel_code', models.CharField(max_length=30)),
('plugin_configuration_id', models.PositiveIntegerField()),
('content_id', models.CharField(max_length=255)),
('resolved', models.BooleanField(default=False)),
('transmission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orphaned_record', to='channel_integration.contentmetadataitemtransmission')),
],
options={
'index_together': {('integrated_channel_code', 'plugin_configuration_id', 'resolved')},
},
),
]
17 changes: 12 additions & 5 deletions channel_integrations/integrated_channel/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class EnterpriseCustomerPluginConfiguration(SoftDeletionModel):

enterprise_customer = models.ForeignKey(
EnterpriseCustomer,
related_name='channelintegration_enterprisecustomerpluginconfiguration',
blank=False,
null=False,
help_text=_("Enterprise Customer associated with the configuration."),
Expand Down Expand Up @@ -537,7 +538,7 @@ class LearnerDataTransmissionAudit(TimeStampedModel):

class Meta:
abstract = True
app_label = 'integrated_channel'
app_label = 'channel_integration'

def __str__(self):
"""
Expand Down Expand Up @@ -613,7 +614,7 @@ class GenericLearnerDataTransmissionAudit(LearnerDataTransmissionAudit):
A generic implementation of LearnerDataTransmissionAudit which can be instantiated
"""
class Meta:
app_label = 'integrated_channel'
app_label = 'channel_integration'

def __str__(self):
"""
Expand Down Expand Up @@ -649,7 +650,11 @@ class Meta:
index_together = [('enterprise_customer', 'integrated_channel_code', 'plugin_configuration_id', 'content_id')]
unique_together = (('integrated_channel_code', 'plugin_configuration_id', 'content_id'),)

enterprise_customer = models.ForeignKey(EnterpriseCustomer, on_delete=models.CASCADE)
enterprise_customer = models.ForeignKey(
EnterpriseCustomer,
related_name='channelintegration_contentmetadataitemtransmission',
on_delete=models.CASCADE
)
integrated_channel_code = models.CharField(max_length=30)
plugin_configuration_id = models.PositiveIntegerField(blank=True, null=True)
content_id = models.CharField(max_length=255)
Expand Down Expand Up @@ -912,7 +917,9 @@ class IntegratedChannelAPIRequestLogs(TimeStampedModel):
"""

enterprise_customer = models.ForeignKey(
EnterpriseCustomer, on_delete=models.CASCADE
EnterpriseCustomer,
related_name='channelintegration_integratedchannelapirequestlogs',
on_delete=models.CASCADE
)
enterprise_customer_configuration_id = models.IntegerField(
blank=False,
Expand All @@ -938,7 +945,7 @@ class IntegratedChannelAPIRequestLogs(TimeStampedModel):
)

class Meta:
app_label = "integrated_channel"
app_label = 'channel_integration'
verbose_name_plural = "Integrated channels API request logs"

def __str__(self):
Expand Down
3 changes: 0 additions & 3 deletions channel_integrations/models.py

This file was deleted.

This file was deleted.

Empty file added default.db
Empty file.
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def is_requirement(line):

include_package_data=True,
install_requires=load_requirements('requirements/base.in'),
python_requires=">=3.12",
python_requires=">=3.11",
license="AGPL 3.0",
zip_safe=False,
keywords='Python edx',
Expand All @@ -155,6 +155,6 @@ def is_requirement(line):
'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
'Natural Language :: English',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.11',
],
)

0 comments on commit 2e91618

Please sign in to comment.