Commit 3e633b07 by Asad Azam Committed by AsadAzam

Added course title and number duplicate validation

parent 2e1ef67f
...@@ -94,7 +94,10 @@ class CustomCourseForm(CourseForm): ...@@ -94,7 +94,10 @@ class CustomCourseForm(CourseForm):
required=True required=True
) )
title = forms.CharField(label=_('Course Title'), required=True) title = forms.CharField(label=_('Course Title'), required=True)
number = forms.CharField(label=_('Course Number'), required=True) number = forms.CharField(
label=_('Course Number'), required=True,
validators=[validate_text_count(max_length=50)]
)
short_description = forms.CharField( short_description = forms.CharField(
label=_('Short Description'), label=_('Short Description'),
widget=forms.Textarea, required=False, validators=[validate_text_count(max_length=255)] widget=forms.Textarea, required=False, validators=[validate_text_count(max_length=255)]
...@@ -191,6 +194,19 @@ class CustomCourseForm(CourseForm): ...@@ -191,6 +194,19 @@ class CustomCourseForm(CourseForm):
if user and not is_internal_user(user): if user and not is_internal_user(user):
self.fields['video_link'].widget = forms.HiddenInput() self.fields['video_link'].widget = forms.HiddenInput()
def clean(self):
cleaned_data = self.cleaned_data
organization = cleaned_data.get("organization")
title = cleaned_data.get("title")
number = cleaned_data.get("number")
instance = getattr(self, 'instance', None)
if not instance.pk:
if Course.objects.filter(title=title, organizations__in=[organization]).exists():
raise ValidationError({'title': _('This course title already exists')})
if Course.objects.filter(number=number, organizations__in=[organization]).exists():
raise ValidationError({'number': _('This course number already exists')})
return cleaned_data
class CourseSearchForm(forms.Form): class CourseSearchForm(forms.Form):
""" Course Type ahead Search Form. """ """ Course Type ahead Search Form. """
......
...@@ -6,7 +6,8 @@ from pytz import timezone ...@@ -6,7 +6,8 @@ from pytz import timezone
from course_discovery.apps.core.models import User from course_discovery.apps.core.models import User
from course_discovery.apps.core.tests.factories import UserFactory from course_discovery.apps.core.tests.factories import UserFactory
from course_discovery.apps.course_metadata.models import Person from course_discovery.apps.course_metadata.models import Person
from course_discovery.apps.course_metadata.tests.factories import PersonFactory from course_discovery.apps.course_metadata.tests.factories import PersonFactory, OrganizationFactory
from course_discovery.apps.publisher.tests.factories import CourseFactory
from course_discovery.apps.publisher.forms import CustomCourseForm, CustomCourseRunForm, PublisherUserCreationForm from course_discovery.apps.publisher.forms import CustomCourseForm, CustomCourseRunForm, PublisherUserCreationForm
...@@ -153,3 +154,41 @@ class PublisherCourseRunEditFormTests(TestCase): ...@@ -153,3 +154,41 @@ class PublisherCourseRunEditFormTests(TestCase):
run_form.cleaned_data['professional_certificate_name'] = "Test Name" run_form.cleaned_data['professional_certificate_name'] = "Test Name"
self.assertEqual(run_form.clean(), run_form.cleaned_data) self.assertEqual(run_form.clean(), run_form.cleaned_data)
class PublisherCustomCourseFormTests(TestCase):
"""
Tests for publisher 'CustomCourseForm'
"""
def setUp(self):
super(PublisherCustomCourseFormTests, self).setUp()
self.course_form = CustomCourseForm()
self.course = CourseFactory(title="Test", number="a123")
self.organization = OrganizationFactory()
self.course.organizations.add(self.organization)
def test_duplicate_title(self):
"""
Verify that clean raises 'ValidationError' if the course title is a duplicate of another course title
within the same organization
"""
course_form = CustomCourseForm()
course_form.cleaned_data = {'title': 'Test', 'number': '123a', 'organization': self.organization}
with self.assertRaises(ValidationError):
course_form.clean()
course_form.cleaned_data['title'] = "Test2"
self.assertEqual(course_form.clean(), course_form.cleaned_data)
def test_duplicate_number(self):
"""
Verify that clean raises 'ValidationError' if the course number is a duplicate of another course number
within the same organization
"""
course_form = CustomCourseForm()
course_form.cleaned_data = {'title': 'Test2', 'number': 'a123', 'organization': self.organization}
with self.assertRaises(ValidationError):
course_form.clean()
course_form.cleaned_data['number'] = "123a"
self.assertEqual(course_form.clean(), course_form.cleaned_data)
...@@ -111,10 +111,9 @@ class CreateCourseViewTests(TestCase): ...@@ -111,10 +111,9 @@ class CreateCourseViewTests(TestCase):
""" """
Verify that user can create course successfully. Verify that user can create course successfully.
""" """
data = {'number': 'testX453', 'image': make_image_file('test_banner.jpg')} data = {'title': 'Test2', 'number': 'testX453', 'image': make_image_file('test_banner.jpg')}
course_dict = self._post_data(data, self.course) course_dict = self._post_data(data, self.course)
response = self.client.post(reverse('publisher:publisher_courses_new'), course_dict) response = self.client.post(reverse('publisher:publisher_courses_new'), course_dict)
course = Course.objects.get(number=course_dict['number']) course = Course.objects.get(number=course_dict['number'])
self.assertRedirects( self.assertRedirects(
...@@ -253,7 +252,7 @@ class CreateCourseViewTests(TestCase): ...@@ -253,7 +252,7 @@ class CreateCourseViewTests(TestCase):
Verify that if add_new_run is checked user is redirected to Verify that if add_new_run is checked user is redirected to
create course run page instead course detail page. create course run page instead course detail page.
""" """
data = {'number': 'testX234', 'image': '', 'add_new_run': True} data = {'title': 'Test2', 'number': 'testX234', 'image': '', 'add_new_run': True}
course_dict = self._post_data(data, self.course) course_dict = self._post_data(data, self.course)
response = self.client.post(reverse('publisher:publisher_courses_new'), course_dict) response = self.client.post(reverse('publisher:publisher_courses_new'), course_dict)
......
...@@ -638,6 +638,14 @@ msgid "Syllabus" ...@@ -638,6 +638,14 @@ msgid "Syllabus"
msgstr "" msgstr ""
#: apps/publisher/forms.py #: apps/publisher/forms.py
msgid "This course title already exists"
msgstr ""
#: apps/publisher/forms.py
msgid "This course number already exists"
msgstr ""
#: apps/publisher/forms.py
msgid "Find Course" msgid "Find Course"
msgstr "" msgstr ""
...@@ -1431,8 +1439,7 @@ msgid "COURSE NUMBER" ...@@ -1431,8 +1439,7 @@ msgid "COURSE NUMBER"
msgstr "" msgstr ""
#: templates/publisher/add_course_form.html #: templates/publisher/add_course_form.html
#: templates/publisher/course_edit_form.html msgid "Maximum 50 characters. Characters can be letters, numbers, or periods."
msgid "Maximum 10 characters. Characters can be letters, numbers, or periods."
msgstr "" msgstr ""
#: templates/publisher/add_course_form.html #: templates/publisher/add_course_form.html
...@@ -1706,6 +1713,10 @@ msgid "255 character limit, including spaces." ...@@ -1706,6 +1713,10 @@ msgid "255 character limit, including spaces."
msgstr "" msgstr ""
#: templates/publisher/course_edit_form.html #: templates/publisher/course_edit_form.html
msgid "Maximum 10 characters. Characters can be letters, numbers, or periods."
msgstr ""
#: templates/publisher/course_edit_form.html
msgid "BIO1.1x, BIO1.2x" msgid "BIO1.1x, BIO1.2x"
msgstr "" msgstr ""
......
...@@ -767,6 +767,16 @@ msgid "Syllabus" ...@@ -767,6 +767,16 @@ msgid "Syllabus"
msgstr "Sýlläßüs Ⱡ'σяєм ιρѕυм ∂#" msgstr "Sýlläßüs Ⱡ'σяєм ιρѕυм ∂#"
#: apps/publisher/forms.py #: apps/publisher/forms.py
msgid "This course title already exists"
msgstr ""
"Thïs çöürsé tïtlé älréädý éxïsts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: apps/publisher/forms.py
msgid "This course number already exists"
msgstr ""
"Thïs çöürsé nümßér älréädý éxïsts Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: apps/publisher/forms.py
msgid "Find Course" msgid "Find Course"
msgstr "Fïnd Çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя #" msgstr "Fïnd Çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя #"
...@@ -1638,10 +1648,9 @@ msgid "COURSE NUMBER" ...@@ -1638,10 +1648,9 @@ msgid "COURSE NUMBER"
msgstr "ÇÖÛRSÉ NÛMBÉR Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#" msgstr "ÇÖÛRSÉ NÛMBÉR Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: templates/publisher/add_course_form.html #: templates/publisher/add_course_form.html
#: templates/publisher/course_edit_form.html msgid "Maximum 50 characters. Characters can be letters, numbers, or periods."
msgid "Maximum 10 characters. Characters can be letters, numbers, or periods."
msgstr "" msgstr ""
"Mäxïmüm 10 çhäräçtérs. Çhäräçtérs çän ßé léttérs, nümßérs, ör pérïöds. " "Mäxïmüm 50 çhäräçtérs. Çhäräçtérs çän ßé léttérs, nümßérs, ör pérïöds. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #" "Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #"
#: templates/publisher/add_course_form.html #: templates/publisher/add_course_form.html
...@@ -1998,6 +2007,12 @@ msgstr "" ...@@ -1998,6 +2007,12 @@ msgstr ""
"¢σηѕє¢тєтυя#" "¢σηѕє¢тєтυя#"
#: templates/publisher/course_edit_form.html #: templates/publisher/course_edit_form.html
msgid "Maximum 10 characters. Characters can be letters, numbers, or periods."
msgstr ""
"Mäxïmüm 10 çhäräçtérs. Çhäräçtérs çän ßé léttérs, nümßérs, ör pérïöds. "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #"
#: templates/publisher/course_edit_form.html
msgid "BIO1.1x, BIO1.2x" msgid "BIO1.1x, BIO1.2x"
msgstr "BÌÖ1.1x, BÌÖ1.2x Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#" msgstr "BÌÖ1.1x, BÌÖ1.2x Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αм#"
......
...@@ -84,6 +84,11 @@ ...@@ -84,6 +84,11 @@
{{ course_form.title.label }} <span class="required">*</span> {{ course_form.title.label }} <span class="required">*</span>
</label> </label>
{{ course_form.title }} {{ course_form.title }}
{% if course_form.title.errors %}
<div class="field-message-content">
{{ course_form.title.errors|escape }}
</div>
{% endif %}
</div> </div>
</div> </div>
...@@ -102,7 +107,7 @@ ...@@ -102,7 +107,7 @@
</div> </div>
<div id="tab-practices" class="content active"> <div id="tab-practices" class="content active">
<ul> <ul>
<li>{% trans "Maximum 10 characters. Characters can be letters, numbers, or periods." %}</li> <li>{% trans "Maximum 50 characters. Characters can be letters, numbers, or periods." %}</li>
<li>{% trans "If a course consists of several modules, the course number can have an ending such as .1x or .2x." %}</li> <li>{% trans "If a course consists of several modules, the course number can have an ending such as .1x or .2x." %}</li>
</ul> </ul>
</div> </div>
...@@ -116,6 +121,11 @@ ...@@ -116,6 +121,11 @@
<div class="col col-6"> <div class="col col-6">
<label class="field-label ">{{ course_form.number.label_tag }} <span class="required">*</span></label> <label class="field-label ">{{ course_form.number.label_tag }} <span class="required">*</span></label>
{{ course_form.number }} {{ course_form.number }}
{% if course_form.number.errors %}
<div class="field-message-content">
{{ course_form.number.errors|escape }}
</div>
{% endif %}
</div> </div>
</div> </div>
</fieldset> </fieldset>
......
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