Commit c686e99f by Awais Committed by Awais Qureshi

Add course assignment roles.

Redirect page towards course-run detail.

Ecom-6091
parent 502eeefe
...@@ -176,6 +176,13 @@ class Course(TimeStampedModel, ChangedByMixin): ...@@ -176,6 +176,13 @@ class Course(TimeStampedModel, ChangedByMixin):
except CourseUserRole.DoesNotExist: except CourseUserRole.DoesNotExist:
return None return None
def assign_organization_role(self, organization):
"""
Create course-user-roles for the given organization against a course.
"""
for user_role in organization.organization_user_roles.all():
CourseUserRole.add_course_roles(self, user_role.role, user_role.user)
class CourseRun(TimeStampedModel, ChangedByMixin): class CourseRun(TimeStampedModel, ChangedByMixin):
""" Publisher CourseRun model. It contains fields related to the course run intake form.""" """ Publisher CourseRun model. It contains fields related to the course run intake form."""
...@@ -403,6 +410,22 @@ class CourseUserRole(TimeStampedModel, ChangedByMixin): ...@@ -403,6 +410,22 @@ class CourseUserRole(TimeStampedModel, ChangedByMixin):
role=self.role role=self.role
) )
@classmethod
def add_course_roles(cls, course, role, user):
"""
Create course roles.
Arguments:
course (obj): course object
role (str): role description
user (obj): User object
Returns:
obj: CourseUserRole object
"""
return cls.objects.get_or_create(course=course, role=role, user=user)
class OrganizationExtension(TimeStampedModel): class OrganizationExtension(TimeStampedModel):
""" Organization-Extension relation model. """ """ Organization-Extension relation model. """
......
...@@ -165,6 +165,32 @@ class CourseTests(TestCase): ...@@ -165,6 +165,32 @@ class CourseTests(TestCase):
self.assertEqual(self.user1, self.course2.partner_coordinator) self.assertEqual(self.user1, self.course2.partner_coordinator)
def test_assign_roles(self):
"""
Verify that method `assign_organization_role' assign course-user-roles
for the organization against a course.
"""
self.assertFalse(self.course2.course_user_roles.all())
# create default roles for organization
factories.OrganizationUserRoleFactory(
role=PublisherUserRole.PartnerCoordinator, organization=self.org_extension_2.organization
)
factories.OrganizationUserRoleFactory(
role=PublisherUserRole.PartnerCoordinator, organization=self.org_extension_2.organization
)
self.course2.assign_organization_role(self.org_extension_2.organization)
self.assertEqual(len(self.course2.course_user_roles.all()), 2)
def test_assign_roles_without_default_roles(self):
"""
Verify that method `assign_organization_role' works fine even if no
default roles exists.
"""
self.course2.assign_organization_role(self.org_extension_2.organization)
self.assertFalse(self.course2.course_user_roles.all())
class SeatTests(TestCase): class SeatTests(TestCase):
""" Tests for the publisher `Seat` model. """ """ Tests for the publisher `Seat` model. """
...@@ -256,6 +282,9 @@ class CourseUserRoleTests(TestCase): ...@@ -256,6 +282,9 @@ class CourseUserRoleTests(TestCase):
def setUp(self): def setUp(self):
super(CourseUserRoleTests, self).setUp() super(CourseUserRoleTests, self).setUp()
self.course_user_role = factories.CourseUserRoleFactory(role=PublisherUserRole.PartnerCoordinator) self.course_user_role = factories.CourseUserRoleFactory(role=PublisherUserRole.PartnerCoordinator)
self.course = factories.CourseFactory()
self.user = UserFactory()
self.marketing_reviewer_role = PublisherUserRole.MarketingReviewer
def test_str(self): def test_str(self):
"""Verify that a CourseUserRole is properly converted to a str.""" """Verify that a CourseUserRole is properly converted to a str."""
...@@ -271,6 +300,32 @@ class CourseUserRoleTests(TestCase): ...@@ -271,6 +300,32 @@ class CourseUserRoleTests(TestCase):
course=self.course_user_role.course, user=self.course_user_role.user, role=self.course_user_role.role course=self.course_user_role.course, user=self.course_user_role.user, role=self.course_user_role.role
) )
def test_add_course_roles(self):
"""
Verify that method `add_course_roles` created the course user role.
"""
course_role, created = CourseUserRole.add_course_roles(
self.course, self.marketing_reviewer_role, self.user
)
self.assertTrue(created)
self.assertEqual(course_role.course, self.course)
self.assertEqual(course_role.user, self.user)
self.assertEqual(course_role.role, self.marketing_reviewer_role)
def test_add_course_roles_with_existing_record(self):
"""
Verify that method `add_course_roles` does not create the duplicate
course user role.
"""
__, created = CourseUserRole.add_course_roles(
self.course, self.marketing_reviewer_role, self.user
)
self.assertTrue(created)
__, created = CourseUserRole.add_course_roles(
self.course, self.marketing_reviewer_role, self.user
)
self.assertFalse(created)
class GroupOrganizationTests(TestCase): class GroupOrganizationTests(TestCase):
"""Tests of the GroupOrganization model.""" """Tests of the GroupOrganization model."""
......
...@@ -56,6 +56,14 @@ class CreateUpdateCourseViewTests(TestCase): ...@@ -56,6 +56,14 @@ class CreateUpdateCourseViewTests(TestCase):
self.client.login(username=self.user.username, password=USER_PASSWORD) self.client.login(username=self.user.username, password=USER_PASSWORD)
self.start_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') self.start_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# creating default organizations roles
factories.OrganizationUserRoleFactory(
role=PublisherUserRole.PartnerCoordinator, organization=self.organization_extension.organization
)
factories.OrganizationUserRoleFactory(
role=PublisherUserRole.MarketingReviewer, organization=self.organization_extension.organization
)
def test_course_form_without_login(self): def test_course_form_without_login(self):
""" Verify that user can't access new course form page when not logged in. """ """ Verify that user can't access new course form page when not logged in. """
self.client.logout() self.client.logout()
...@@ -282,9 +290,11 @@ class CreateUpdateCourseViewTests(TestCase): ...@@ -282,9 +290,11 @@ class CreateUpdateCourseViewTests(TestCase):
def _assert_test_data(self, response, course, expected_type, expected_price): def _assert_test_data(self, response, course, expected_type, expected_price):
# DRY method to assert response and data. # DRY method to assert response and data.
run_detail_path = reverse('publisher:publisher_course_run_detail', kwargs={'pk': course.id})
self.assertRedirects( self.assertRedirects(
response, response,
expected_url=reverse('publisher:publisher_courses_readonly', kwargs={'pk': course.id}), expected_url=run_detail_path,
status_code=302, status_code=302,
target_status_code=200 target_status_code=200
) )
...@@ -297,13 +307,15 @@ class CreateUpdateCourseViewTests(TestCase): ...@@ -297,13 +307,15 @@ class CreateUpdateCourseViewTests(TestCase):
self.assertEqual(seat.type, expected_type) self.assertEqual(seat.type, expected_type)
self.assertEqual(seat.price, expected_price) self.assertEqual(seat.price, expected_price)
self._assert_records(2) self._assert_records(2)
response = self.client.get(reverse('publisher:publisher_courses_readonly', kwargs={'pk': course.id})) response = self.client.get(run_detail_path)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# django-taggit stores data without any order. For test . # django-taggit stores data without any order. For test .
self.assertEqual(sorted([c.name for c in course.keywords.all()]), ['abc', 'def', 'xyz']) self.assertEqual(sorted([c.name for c in course.keywords.all()]), ['abc', 'def', 'xyz'])
self.assertEqual(course.organizations.first(), self.organization_extension.organization) self.assertEqual(course.organizations.first(), self.organization_extension.organization)
self.assertTrue(len(course.course_user_roles.all()), 2)
class CreateUpdateCourseRunViewTests(TestCase): class CreateUpdateCourseRunViewTests(TestCase):
""" Tests for the publisher `CreateCourseRunView` and `UpdateCourseRunView`. """ """ Tests for the publisher `CreateCourseRunView` and `UpdateCourseRunView`. """
......
...@@ -162,7 +162,7 @@ class CreateCourseView(mixins.LoginRequiredMixin, CreateView): ...@@ -162,7 +162,7 @@ class CreateCourseView(mixins.LoginRequiredMixin, CreateView):
run_form = CustomCourseRunForm run_form = CustomCourseRunForm
seat_form = CustomSeatForm seat_form = CustomSeatForm
template_name = 'publisher/add_course_form.html' template_name = 'publisher/add_course_form.html'
success_url = 'publisher:publisher_courses_readonly' success_url = 'publisher:publisher_course_run_detail'
def get_success_url(self, course_id): # pylint: disable=arguments-differ def get_success_url(self, course_id): # pylint: disable=arguments-differ
return reverse(self.success_url, kwargs={'pk': course_id}) return reverse(self.success_url, kwargs={'pk': course_id})
...@@ -212,14 +212,21 @@ class CreateCourseView(mixins.LoginRequiredMixin, CreateView): ...@@ -212,14 +212,21 @@ class CreateCourseView(mixins.LoginRequiredMixin, CreateView):
) )
course.organizations.add(organization_extension.organization) course.organizations.add(organization_extension.organization)
# add default organization roles into course-user-roles
course.assign_organization_role(organization_extension.organization)
messages.success( messages.success(
request, _('Course created successfully.') request, _('Course created successfully.')
) )
return HttpResponseRedirect(self.get_success_url(course.id)) return HttpResponseRedirect(self.get_success_url(run_course.id))
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
messages.error(request, str(e)) # pylint: disable=no-member
error_message = _('An error occurred while saving your changes. {error}').format(error=str(e))
messages.error(request, error_message)
if not messages.get_messages(request):
messages.error(request, _('Please fill all required fields.'))
messages.error(request, _('Please fill all required field.'))
ctx.update( ctx.update(
{ {
'course_form': course_form, 'course_form': course_form,
......
...@@ -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: 2016-12-28 15:53-0500\n" "POT-Creation-Date: 2016-12-29 14:13+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
...@@ -604,21 +604,22 @@ msgid "Course created successfully." ...@@ -604,21 +604,22 @@ msgid "Course created successfully."
msgstr "" msgstr ""
#: apps/publisher/views.py #: apps/publisher/views.py
msgid "Please fill all required field." #, python-brace-format
msgid "An error occurred while saving your changes. {error}"
msgstr "" msgstr ""
#: apps/publisher/views.py #: apps/publisher/views.py
#, python-brace-format msgid "Please fill all required fields."
msgid "Course run created successfully for course \"{course_title}\"."
msgstr "" msgstr ""
#: apps/publisher/views.py #: apps/publisher/views.py
#, python-brace-format #, python-brace-format
msgid "There was an error saving course run, {error}" msgid "Course run created successfully for course \"{course_title}\"."
msgstr "" msgstr ""
#: apps/publisher/views.py #: apps/publisher/views.py
msgid "Please fill all required fields." #, python-brace-format
msgid "There was an error saving course run, {error}"
msgstr "" msgstr ""
#: apps/publisher/views.py #: apps/publisher/views.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: 2016-12-28 15:53-0500\n" "POT-Creation-Date: 2016-12-29 14:13+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: 2016-12-28 15:53-0500\n" "POT-Creation-Date: 2016-12-29 14:13+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
...@@ -726,8 +726,16 @@ msgid "Course created successfully." ...@@ -726,8 +726,16 @@ msgid "Course created successfully."
msgstr "Çöürsé çréätéd süççéssfüllý. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#" msgstr "Çöürsé çréätéd süççéssfüllý. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#"
#: apps/publisher/views.py #: apps/publisher/views.py
msgid "Please fill all required field." #, python-brace-format
msgstr "Pléäsé fïll äll réqüïréd fïéld. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" msgid "An error occurred while saving your changes. {error}"
msgstr ""
"Àn érrör öççürréd whïlé sävïng ýöür çhängés. {error} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя α#"
#: apps/publisher/views.py
msgid "Please fill all required fields."
msgstr ""
"Pléäsé fïll äll réqüïréd fïélds. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: apps/publisher/views.py #: apps/publisher/views.py
#, python-brace-format #, python-brace-format
...@@ -744,11 +752,6 @@ msgstr "" ...@@ -744,11 +752,6 @@ msgstr ""
"¢σηѕє¢тєтυя #" "¢σηѕє¢тєтυя #"
#: apps/publisher/views.py #: apps/publisher/views.py
msgid "Please fill all required fields."
msgstr ""
"Pléäsé fïll äll réqüïréd fïélds. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: apps/publisher/views.py
#, python-brace-format #, python-brace-format
msgid "Content moved to `{state}` successfully." msgid "Content moved to `{state}` successfully."
msgstr "" msgstr ""
......
...@@ -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: 2016-12-28 15:53-0500\n" "POT-Creation-Date: 2016-12-29 14:13+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
......
...@@ -13,15 +13,11 @@ ...@@ -13,15 +13,11 @@
<div class="alert-messages"> <div class="alert-messages">
{% if messages %} {% if messages %}
{% for message in messages %} {% for message in messages %}
<div class="alert alert-{{ message.tags }}" role="alert" aria-labelledby="alert-title-{{ message.tags }}" tabindex="-1"> <div class="alert alert-{{ message.tags }}" role="alert" aria-labelledby="alert-title-{{ message.tags }}" tabindex="-1">
<div class="alert-message-with-action"> <div><p class="alert-copy">{{ message }}</p></div>
<p class="alert-copy">
{{ message }}
</p>
</div> </div>
</div> {% endfor %}
{% endfor %}
{% endif %} {% endif %}
<form class="form" method="post" action="" enctype="multipart/form-data"> <form class="form" method="post" action="" enctype="multipart/form-data">
......
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