Commit cff1247d by Matthew Piatetsky

Add reporting type field

ECOM-7021
parent a604def4
...@@ -392,7 +392,7 @@ class CourseRunSerializer(MinimalCourseRunSerializer): ...@@ -392,7 +392,7 @@ class CourseRunSerializer(MinimalCourseRunSerializer):
fields = MinimalCourseRunSerializer.Meta.fields + ( fields = MinimalCourseRunSerializer.Meta.fields + (
'course', 'full_description', 'announcement', 'video', 'seats', 'content_language', 'course', 'full_description', 'announcement', 'video', 'seats', 'content_language',
'transcript_languages', 'instructors', 'staff', 'min_effort', 'max_effort', 'modified', 'transcript_languages', 'instructors', 'staff', 'min_effort', 'max_effort', 'modified',
'level_type', 'availability', 'mobile_available', 'hidden', 'level_type', 'availability', 'mobile_available', 'hidden', 'reporting_type',
) )
def get_instructors(self, obj): # pylint: disable=unused-argument def get_instructors(self, obj): # pylint: disable=unused-argument
......
...@@ -321,6 +321,7 @@ class CourseRunSerializerTests(MinimalCourseRunSerializerTests): ...@@ -321,6 +321,7 @@ class CourseRunSerializerTests(MinimalCourseRunSerializerTests):
'modified': json_date_format(course_run.modified), # pylint: disable=no-member 'modified': json_date_format(course_run.modified), # pylint: disable=no-member
'level_type': course_run.level_type.name, 'level_type': course_run.level_type.name,
'availability': course_run.availability, 'availability': course_run.availability,
'reporting_type': course_run.reporting_type,
}) })
return expected return expected
......
...@@ -147,10 +147,10 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi ...@@ -147,10 +147,10 @@ class CatalogViewSetTests(ElasticsearchTestMixin, SerializationMixin, OAuth2Mixi
for course_run in excluded_runs: for course_run in excluded_runs:
SeatFactory(course_run=course_run) SeatFactory(course_run=course_run)
with self.assertNumQueries(42): with self.assertNumQueries(28):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertListEqual(response.data['results'], self.serialize_catalog_course(courses, many=True)) assert response.data['results'] == self.serialize_catalog_course(courses, many=True)
def test_contains(self): def test_contains(self):
""" Verify the endpoint returns a filtered list of courses contained in the catalog. """ """ Verify the endpoint returns a filtered list of courses contained in the catalog. """
......
...@@ -42,7 +42,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -42,7 +42,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
with self.assertNumQueries(9): with self.assertNumQueries(9):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(response.data, self.serialize_course_run(self.course_run)) self.assertEqual(response.data, self.serialize_course_run(self.course_run))
def test_get_exclude_deleted_programs(self): def test_get_exclude_deleted_programs(self):
...@@ -53,8 +53,8 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -53,8 +53,8 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
with self.assertNumQueries(12): with self.assertNumQueries(12):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(response.data.get('programs'), []) assert response.data.get('programs') == []
def test_get_include_deleted_programs(self): def test_get_include_deleted_programs(self):
""" """
...@@ -66,13 +66,11 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -66,13 +66,11 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key}) url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
url += '?include_deleted_programs=1' url += '?include_deleted_programs=1'
with self.assertNumQueries(20): with self.assertNumQueries(12):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual( assert response.data == \
response.data,
self.serialize_course_run(self.course_run, extra_context={'include_deleted_programs': True}) self.serialize_course_run(self.course_run, extra_context={'include_deleted_programs': True})
)
def test_get_exclude_unpublished_programs(self): def test_get_exclude_unpublished_programs(self):
""" Verify the endpoint returns no associated unpublished programs """ """ Verify the endpoint returns no associated unpublished programs """
...@@ -82,7 +80,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -82,7 +80,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
with self.assertNumQueries(12): with self.assertNumQueries(12):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(response.data.get('programs'), []) self.assertEqual(response.data.get('programs'), [])
def test_get_include_unpublished_programs(self): def test_get_include_unpublished_programs(self):
...@@ -95,13 +93,11 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -95,13 +93,11 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key}) url = reverse('api:v1:course_run-detail', kwargs={'key': self.course_run.key})
url += '?include_unpublished_programs=1' url += '?include_unpublished_programs=1'
with self.assertNumQueries(20): with self.assertNumQueries(12):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual( assert response.data == \
response.data,
self.serialize_course_run(self.course_run, extra_context={'include_unpublished_programs': True}) self.serialize_course_run(self.course_run, extra_context={'include_unpublished_programs': True})
)
def test_list(self): def test_list(self):
""" Verify the endpoint returns a list of all catalogs. """ """ Verify the endpoint returns a list of all catalogs. """
...@@ -110,7 +106,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -110,7 +106,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
with self.assertNumQueries(11): with self.assertNumQueries(11):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertListEqual( self.assertListEqual(
response.data['results'], response.data['results'],
self.serialize_course_run(CourseRun.objects.all().order_by(Lower('key')), many=True) self.serialize_course_run(CourseRun.objects.all().order_by(Lower('key')), many=True)
...@@ -123,7 +119,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -123,7 +119,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
with self.assertNumQueries(11): with self.assertNumQueries(11):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertListEqual( self.assertListEqual(
response.data['results'], response.data['results'],
self.serialize_course_run(CourseRun.objects.all().order_by('start'), many=True) self.serialize_course_run(CourseRun.objects.all().order_by('start'), many=True)
...@@ -156,7 +152,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -156,7 +152,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
def assert_list_results(self, url, expected, extra_context=None): def assert_list_results(self, url, expected, extra_context=None):
expected = sorted(expected, key=lambda course_run: course_run.key.lower()) expected = sorted(expected, key=lambda course_run: course_run.key.lower())
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertListEqual( self.assertListEqual(
response.data['results'], response.data['results'],
self.serialize_course_run(expected, many=True, extra_context=extra_context) self.serialize_course_run(expected, many=True, extra_context=extra_context)
...@@ -232,7 +228,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -232,7 +228,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = '{}?{}'.format(reverse('api:v1:course_run-contains'), qs) url = '{}?{}'.format(reverse('api:v1:course_run-contains'), qs)
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual( self.assertEqual(
response.data, response.data,
{ {
...@@ -262,7 +258,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC ...@@ -262,7 +258,7 @@ class CourseRunViewSetTests(SerializationMixin, ElasticsearchTestMixin, APITestC
url = '{}?{}'.format(reverse('api:v1:course_run-contains'), qs) url = '{}?{}'.format(reverse('api:v1:course_run-contains'), qs)
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertDictEqual( self.assertDictEqual(
response.data, response.data,
{ {
......
...@@ -51,7 +51,7 @@ class ProgramViewSetTests(SerializationMixin, APITestCase): ...@@ -51,7 +51,7 @@ class ProgramViewSetTests(SerializationMixin, APITestCase):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, self.serialize_program(program)) return response
def test_authentication(self): def test_authentication(self):
""" Verify the endpoint requires the user to be authenticated. """ """ Verify the endpoint requires the user to be authenticated. """
...@@ -65,8 +65,9 @@ class ProgramViewSetTests(SerializationMixin, APITestCase): ...@@ -65,8 +65,9 @@ class ProgramViewSetTests(SerializationMixin, APITestCase):
def test_retrieve(self): def test_retrieve(self):
""" Verify the endpoint returns the details for a single program. """ """ Verify the endpoint returns the details for a single program. """
program = self.create_program() program = self.create_program()
with self.assertNumQueries(76): with self.assertNumQueries(31):
self.assert_retrieve_success(program) response = self.assert_retrieve_success(program)
assert response.data == self.serialize_program(program)
@ddt.data(True, False) @ddt.data(True, False)
def test_retrieve_with_sorting_flag(self, order_courses_by_start_date): def test_retrieve_with_sorting_flag(self, order_courses_by_start_date):
...@@ -75,16 +76,18 @@ class ProgramViewSetTests(SerializationMixin, APITestCase): ...@@ -75,16 +76,18 @@ class ProgramViewSetTests(SerializationMixin, APITestCase):
for course in course_list: for course in course_list:
CourseRunFactory(course=course) CourseRunFactory(course=course)
program = ProgramFactory(courses=course_list, order_courses_by_start_date=order_courses_by_start_date) program = ProgramFactory(courses=course_list, order_courses_by_start_date=order_courses_by_start_date)
with self.assertNumQueries(90): with self.assertNumQueries(26):
self.assert_retrieve_success(program) response = self.assert_retrieve_success(program)
assert response.data == self.serialize_program(program)
self.assertEqual(course_list, list(program.courses.all())) # pylint: disable=no-member self.assertEqual(course_list, list(program.courses.all())) # pylint: disable=no-member
def test_retrieve_without_course_runs(self): def test_retrieve_without_course_runs(self):
""" Verify the endpoint returns data for a program even if the program's courses have no course runs. """ """ Verify the endpoint returns data for a program even if the program's courses have no course runs. """
course = CourseFactory() course = CourseFactory()
program = ProgramFactory(courses=[course]) program = ProgramFactory(courses=[course])
with self.assertNumQueries(49): with self.assertNumQueries(19):
self.assert_retrieve_success(program) response = self.assert_retrieve_success(program)
assert response.data == self.serialize_program(program)
def assert_list_results(self, url, expected, expected_query_count, extra_context=None): def assert_list_results(self, url, expected, expected_query_count, extra_context=None):
""" """
......
...@@ -20,3 +20,11 @@ class ProgramStatus(DjangoChoices): ...@@ -20,3 +20,11 @@ class ProgramStatus(DjangoChoices):
Active = ChoiceItem('active', _('Active')) Active = ChoiceItem('active', _('Active'))
Retired = ChoiceItem('retired', _('Retired')) Retired = ChoiceItem('retired', _('Retired'))
Deleted = ChoiceItem('deleted', _('Deleted')) Deleted = ChoiceItem('deleted', _('Deleted'))
class ReportingType(DjangoChoices):
mooc = ChoiceItem('mooc', 'mooc')
spoc = ChoiceItem('spoc', 'spoc')
test = ChoiceItem('test', 'test')
demo = ChoiceItem('demo', 'demo')
other = ChoiceItem('other', 'other')
# -*- coding: utf-8 -*-
# Generated by Django 1.9.11 on 2017-02-06 20:45
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('course_metadata', '0045_person_profile_image'),
]
operations = [
migrations.AddField(
model_name='courserun',
name='reporting_type',
field=models.CharField(choices=[('mooc', 'mooc'), ('spoc', 'spoc'), ('test', 'test'), ('demo', 'demo'), ('other', 'other')], default='mooc', max_length=255),
),
]
...@@ -21,7 +21,9 @@ from stdimage.utils import UploadToAutoSlug ...@@ -21,7 +21,9 @@ from stdimage.utils import UploadToAutoSlug
from taggit_autosuggest.managers import TaggableManager from taggit_autosuggest.managers import TaggableManager
from course_discovery.apps.core.models import Currency, Partner from course_discovery.apps.core.models import Currency, Partner
from course_discovery.apps.course_metadata.choices import CourseRunStatus, CourseRunPacing, ProgramStatus from course_discovery.apps.course_metadata.choices import (
CourseRunStatus, CourseRunPacing, ProgramStatus, ReportingType
)
from course_discovery.apps.course_metadata.publishers import MarketingSitePublisher from course_discovery.apps.course_metadata.publishers import MarketingSitePublisher
from course_discovery.apps.course_metadata.query import CourseQuerySet, CourseRunQuerySet, ProgramQuerySet from course_discovery.apps.course_metadata.query import CourseQuerySet, CourseRunQuerySet, ProgramQuerySet
from course_discovery.apps.course_metadata.utils import UploadToFieldNamePath from course_discovery.apps.course_metadata.utils import UploadToFieldNamePath
...@@ -389,6 +391,7 @@ class CourseRun(TimeStampedModel): ...@@ -389,6 +391,7 @@ class CourseRun(TimeStampedModel):
default=False, default=False,
help_text=_('Indicates whether the course relation has been manually overridden.') help_text=_('Indicates whether the course relation has been manually overridden.')
) )
reporting_type = models.CharField(max_length=255, choices=ReportingType.choices, default=ReportingType.mooc)
tags = TaggableManager( tags = TaggableManager(
blank=True, blank=True,
......
...@@ -6,7 +6,9 @@ from pytz import UTC ...@@ -6,7 +6,9 @@ from pytz import UTC
from course_discovery.apps.core.tests.factories import PartnerFactory from course_discovery.apps.core.tests.factories import PartnerFactory
from course_discovery.apps.core.tests.utils import FuzzyURL from course_discovery.apps.core.tests.utils import FuzzyURL
from course_discovery.apps.course_metadata.choices import CourseRunStatus, CourseRunPacing, ProgramStatus from course_discovery.apps.course_metadata.choices import (
CourseRunStatus, CourseRunPacing, ProgramStatus, ReportingType
)
from course_discovery.apps.course_metadata.models import * # pylint: disable=wildcard-import from course_discovery.apps.course_metadata.models import * # pylint: disable=wildcard-import
from course_discovery.apps.ietf_language_tags.models import LanguageTag from course_discovery.apps.ietf_language_tags.models import LanguageTag
...@@ -126,6 +128,7 @@ class CourseRunFactory(factory.DjangoModelFactory): ...@@ -126,6 +128,7 @@ class CourseRunFactory(factory.DjangoModelFactory):
min_effort = FuzzyInteger(1, 10) min_effort = FuzzyInteger(1, 10)
max_effort = FuzzyInteger(10, 20) max_effort = FuzzyInteger(10, 20)
pacing_type = FuzzyChoice([name for name, __ in CourseRunPacing.choices]) pacing_type = FuzzyChoice([name for name, __ in CourseRunPacing.choices])
reporting_type = FuzzyChoice([name for name, __ in ReportingType.choices])
slug = FuzzyText() slug = FuzzyText()
hidden = False hidden = False
weeks_to_complete = FuzzyInteger(1) weeks_to_complete = FuzzyInteger(1)
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-03 14:30-0500\n" "POT-Creation-Date: 2017-02-06 16:34-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: apps/api/filters.py #: apps/api/filters.py
#, python-brace-format #, python-brace-format
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-03 14:30-0500\n" "POT-Creation-Date: 2017-02-06 16:34-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: static/js/catalogs-change-form.js #: static/js/catalogs-change-form.js
msgid "Preview" msgid "Preview"
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-03 14:30-0500\n" "POT-Creation-Date: 2017-02-06 16:34-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps/api/filters.py #: apps/api/filters.py
......
...@@ -7,14 +7,14 @@ msgid "" ...@@ -7,14 +7,14 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-03 14:30-0500\n" "POT-Creation-Date: 2017-02-06 16:34-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: static/js/catalogs-change-form.js #: static/js/catalogs-change-form.js
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment