From 222267084ceee8f0396250182abd3675f445dfca Mon Sep 17 00:00:00 2001 From: muhammad-ammar Date: Wed, 20 Sep 2017 12:24:51 +0500 Subject: [PATCH] Organization specific transcript credentials state EDUCATOR-1376 --- edxval/admin.py | 9 ++- edxval/api.py | 43 +++++++++++- .../0007_transcript_credentials_state.py | 32 +++++++++ edxval/models.py | 41 ++++++++++++ edxval/tests/test_api.py | 65 ++++++++++++++++++- 5 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 edxval/migrations/0007_transcript_credentials_state.py diff --git a/edxval/admin.py b/edxval/admin.py index 0b21dcff..14146372 100644 --- a/edxval/admin.py +++ b/edxval/admin.py @@ -5,7 +5,7 @@ from django.contrib import admin from .models import (CourseVideo, EncodedVideo, Profile, TranscriptPreference, - Video, VideoImage, VideoTranscript) + Video, VideoImage, VideoTranscript, ThirdPartyTranscriptCredentialsState) class ProfileAdmin(admin.ModelAdmin): # pylint: disable=C0111 @@ -48,9 +48,16 @@ class CourseVideoAdmin(admin.ModelAdmin): verbose_name_plural = 'Course Videos' +class ThirdPartyTranscriptCredentialsStateAdmin(admin.ModelAdmin): + model = ThirdPartyTranscriptCredentialsState + verbose_name = 'Organization Transcript Credential State' + verbose_name_plural = 'Organization Transcript Credentials State' + + admin.site.register(Profile, ProfileAdmin) admin.site.register(Video, VideoAdmin) admin.site.register(VideoTranscript) admin.site.register(TranscriptPreference) admin.site.register(VideoImage, VideoImageAdmin) admin.site.register(CourseVideo, CourseVideoAdmin) +admin.site.register(ThirdPartyTranscriptCredentialsState, ThirdPartyTranscriptCredentialsStateAdmin) diff --git a/edxval/api.py b/edxval/api.py index 8481afc6..72fdf354 100644 --- a/edxval/api.py +++ b/edxval/api.py @@ -17,7 +17,7 @@ from edxval.models import (CourseVideo, EncodedVideo, Profile, TranscriptFormat, TranscriptPreference, TranscriptProviderType, Video, VideoImage, - VideoTranscript) + VideoTranscript, ThirdPartyTranscriptCredentialsState) from edxval.serializers import TranscriptPreferenceSerializer, TranscriptSerializer, VideoSerializer from edxval.utils import THIRD_PARTY_TRANSCRIPTION_PLANS @@ -143,6 +143,47 @@ def update_video_status(edx_video_id, status): video.save() +def get_transcript_credentials_state_for_org(org, provider=None): + """ + Returns transcript credentials state for an org + + Arguments: + org (unicode): course organization + provider (unicode): transcript provider + + Returns: + dict: provider name and their credential existance map + + { + u'Cielo24': True + } + { + u'3PlayMedia': False, + u'Cielo24': True + } + """ + query_filter = {'org': org} + if provider: + query_filter['provider'] = provider + + return { + credential.provider: credential.exists + for credential in ThirdPartyTranscriptCredentialsState.objects.filter(**query_filter) + } + + +def update_transcript_credentials_state_for_org(org, provider, exists): + """ + Updates transcript credentials state for a course organization. + + Arguments: + org (unicode): course organization + provider (unicode): transcript provider + exists (bool): state of credentials + """ + ThirdPartyTranscriptCredentialsState.update_or_create(org, provider, exists) + + def is_transcript_available(video_id, language_code=None): """ Returns whether the transcripts are available for a video. diff --git a/edxval/migrations/0007_transcript_credentials_state.py b/edxval/migrations/0007_transcript_credentials_state.py new file mode 100644 index 00000000..b6e414cb --- /dev/null +++ b/edxval/migrations/0007_transcript_credentials_state.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-10-10 08:15 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone +import model_utils.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('edxval', '0006_auto_20171009_0725'), + ] + + operations = [ + migrations.CreateModel( + name='ThirdPartyTranscriptCredentialsState', + 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')), + ('org', models.CharField(max_length=32, verbose_name=b'Course Organization')), + ('provider', models.CharField(choices=[(b'Custom', b'Custom'), (b'3PlayMedia', b'3PlayMedia'), (b'Cielo24', b'Cielo24')], max_length=20, verbose_name=b'Transcript Provider')), + ('exists', models.BooleanField(default=False, help_text=b'Transcript credentials state')), + ], + ), + migrations.AlterUniqueTogether( + name='thirdpartytranscriptcredentialsstate', + unique_together=set([('org', 'provider')]), + ), + ] diff --git a/edxval/models.py b/edxval/models.py index 7633f79f..6b50ed74 100644 --- a/edxval/models.py +++ b/edxval/models.py @@ -612,6 +612,47 @@ def __unicode__(self): return u'{course_id} - {provider}'.format(course_id=self.course_id, provider=self.provider) +class ThirdPartyTranscriptCredentialsState(TimeStampedModel): + """ + State of transcript credentials for a course organization + """ + class Meta: + unique_together = ('org', 'provider') + + org = models.CharField(verbose_name='Course Organization', max_length=32) + provider = models.CharField( + verbose_name='Transcript Provider', + max_length=20, + choices=TranscriptProviderType.CHOICES, + ) + exists = models.BooleanField(default=False, help_text='Transcript credentials state') + + @classmethod + def update_or_create(cls, org, provider, exists): + """ + Update or create credentials state. + """ + instance, created = cls.objects.update_or_create( + org=org, + provider=provider, + defaults={'exists': exists}, + ) + + return instance, created + + def __unicode__(self): + """ + Returns unicode representation of provider credentials state for an organization. + + NOTE: Message will look like below: + edX has Cielo24 credentials + edX doesn't have 3PlayMedia credentials + """ + return u'{org} {state} {provider} credentials'.format( + org=self.org, provider=self.provider, state='has' if self.exists else "doesn't have" + ) + + @receiver(models.signals.post_save, sender=Video) def video_status_update_callback(sender, **kwargs): # pylint: disable=unused-argument """ diff --git a/edxval/tests/test_api.py b/edxval/tests/test_api.py index 368d4a32..2aefb3f5 100644 --- a/edxval/tests/test_api.py +++ b/edxval/tests/test_api.py @@ -25,7 +25,7 @@ VideoSortField) from edxval.models import (LIST_MAX_ITEMS, CourseVideo, EncodedVideo, Profile, TranscriptFormat, TranscriptProviderType, Video, - VideoImage, VideoTranscript, TranscriptPreference) + VideoImage, VideoTranscript, TranscriptPreference, ThirdPartyTranscriptCredentialsState) from edxval.tests import APIAuthTestCase, constants from edxval import utils @@ -2045,3 +2045,66 @@ def test_create_transcript_preferences(self): # Verify that there should be 2 preferences exists self.assertEqual(TranscriptPreference.objects.count(), 2) + + +@ddt +class TranscripCredentialsStateTest(TestCase): + """ + ThirdPartyTranscriptCredentialsState Tests + """ + def setUp(self): + """ + Tests setup + """ + ThirdPartyTranscriptCredentialsState.objects.create( + org='edX', provider='Cielo24', exists=True + ) + ThirdPartyTranscriptCredentialsState.objects.create( + org='edX', provider='3PlayMedia', exists=False + ) + + @data( + {'org': 'MAX', 'provider': 'Cielo24', 'exists': True}, + {'org': 'MAX', 'provider': '3PlayMedia', 'exists': True}, + {'org': 'edx', 'provider': '3PlayMedia', 'exists': True}, + ) + @unpack + def test_credentials_state_update(self, **kwargs): + """ + Verify that `update_transcript_credentials_state_for_org` method works as expected + """ + api.update_transcript_credentials_state_for_org(**kwargs) + + credentials_state = ThirdPartyTranscriptCredentialsState.objects.get(org=kwargs['org']) + for key in kwargs: + self.assertEqual(getattr(credentials_state, key), kwargs[key]) + + @data( + { + 'org': 'edX', + 'provider': 'Cielo24', + 'result': {u'Cielo24': True} + }, + { + 'org': 'edX', + 'provider': '3PlayMedia', + 'result': {u'3PlayMedia': False} + }, + { + 'org': 'edX', + 'provider': None, + 'result': {u'3PlayMedia': False, u'Cielo24': True} + }, + { + 'org': 'does_not_exist', + 'provider': 'does_not_exist', + 'result': {} + }, + ) + @unpack + def test_get_credentials_state(self, org, provider, result): + """ + Verify that `get_transcript_credentials_state_for_org` method works as expected + """ + credentials_state = api.get_transcript_credentials_state_for_org(org=org, provider=provider) + self.assertEqual(credentials_state, result)