Repository: kartoza/prj.app

Issue:
Feature: register participant and add using checkbox in the same screen
It would be easier to reduce the amount of steps to add the participants to the course.
In the screen where we add the participant to the list, it should be possible to check a box to automatically add the participant to the course.


Discussion:

Resolving patch:
diff --git a/django_project/certification/admin.py b/django_project/certification/admin.py
--- a/django_project/certification/admin.py
+++ b/django_project/certification/admin.py
@@ -28,7 +28,8 @@ def queryset(self, request):
 
 class AttendeeAdmin(admin.ModelAdmin):
     """Attendee admin model."""
-    list_display = ('firstname', 'surname', 'email')
+    list_display = ('firstname', 'surname', 'email', 'certifying_organisation')
+    search_fields = ['firstname', 'surname']
 
     def queryset(self, request):
         """Ensure we use the correct manager.
diff --git a/django_project/certification/forms.py b/django_project/certification/forms.py
--- a/django_project/certification/forms.py
+++ b/django_project/certification/forms.py
@@ -359,6 +359,12 @@ def save(self, commit=True):
 
 class AttendeeForm(forms.ModelForm):
 
+    add_to_course = forms.BooleanField(
+        initial=True,
+        help_text='Add this attendee to course.',
+        required=False
+    )
+
     class Meta:
         model = Attendee
         fields = (
@@ -379,6 +385,7 @@ def __init__(self, *args, **kwargs):
                 Field('firstname', css_class='form-control'),
                 Field('surname', css_class='form-control'),
                 Field('email', css_class='form-control'),
+                Field('add_to_course', css_class='form-control')
             )
         )
         self.helper.layout = layout
diff --git a/django_project/certification/views/attendee.py b/django_project/certification/views/attendee.py
--- a/django_project/certification/views/attendee.py
+++ b/django_project/certification/views/attendee.py
@@ -33,12 +33,20 @@ def get_success_url(self):
        :returns: URL
        :rtype: HttpResponse
        """
-
-        return reverse('courseattendee-create', kwargs={
-            'project_slug': self.project_slug,
-            'organisation_slug': self.organisation_slug,
-            'slug': self.course_slug,
-        })
+        add_to_course = self.request.POST.get('add_to_course')
+        if add_to_course is None:
+            success_url = reverse('courseattendee-create', kwargs={
+                'project_slug': self.project_slug,
+                'organisation_slug': self.organisation_slug,
+                'slug': self.course_slug,
+            })
+        else:
+            success_url = reverse('course-detail', kwargs={
+                'project_slug': self.project_slug,
+                'organisation_slug': self.organisation_slug,
+                'slug': self.course_slug,
+            })
+        return success_url
 
     def get_context_data(self, **kwargs):
         """Get the context data which is passed to a template.
@@ -73,6 +81,24 @@ def get_form_kwargs(self):
         })
         return kwargs
 
+    def form_valid(self, form):
+        add_to_course = self.request.POST.get('add_to_course')
+        if add_to_course is None:
+            if form.is_valid():
+                form.save()
+        else:
+            if form.is_valid():
+                object = form.save()
+                course_slug = self.kwargs.get('slug', None)
+                course = Course.objects.get(slug=course_slug)
+                course_attendee = CourseAttendee(
+                    attendee=object,
+                    course=course,
+                    author=self.request.user
+                )
+                course_attendee.save()
+        return super(AttendeeCreateView, self).form_valid(form)
+
 
 class CsvUploadView(FormMessagesMixin, LoginRequiredMixin, FormView):
     """


Test patch:
diff --git a/django_project/certification/tests/test_attendee_views.py b/django_project/certification/tests/test_attendee_views.py
new file mode 100644
--- /dev/null
+++ b/django_project/certification/tests/test_attendee_views.py
@@ -0,0 +1,148 @@
+# coding=utf-8
+from django.core.urlresolvers import reverse
+from django.test import TestCase, override_settings
+from django.test.client import Client
+from base.tests.model_factories import ProjectF
+from certification.tests.model_factories import (
+    CertifyingOrganisationF,
+    TrainingCenterF,
+    CourseF,
+    CourseConvenerF,
+    CourseTypeF,
+)
+from core.model_factories import UserF
+import logging
+
+
+class TestCourseAttendeeView(TestCase):
+    """Tests that attendee and course attendee view works."""
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def setUp(self):
+        self.client = Client()
+        self.client.post(
+            '/set_language/', data={'language': 'en'})
+        logging.disable(logging.CRITICAL)
+        self.project = ProjectF.create()
+        self.certifying_organisation = \
+            CertifyingOrganisationF.create(project=self.project)
+        self.training_center = \
+            TrainingCenterF.create(
+                certifying_organisation=self.certifying_organisation)
+        self.course_convener = \
+            CourseConvenerF.create(
+                certifying_organisation=self.certifying_organisation)
+        self.course_type = \
+            CourseTypeF.create(
+                certifying_organisation=self.certifying_organisation)
+        self.course = CourseF.create(
+            certifying_organisation=self.certifying_organisation,
+            training_center=self.training_center,
+            course_convener=self.course_convener,
+            course_type=self.course_type
+        )
+        self.user = UserF.create(**{
+            'username': 'anita',
+            'password': 'password',
+            'is_staff': True
+        })
+        self.user.set_password('password')
+        self.user.save()
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def tearDown(self):
+        """
+        Teardown after each test.
+
+        :return:
+        """
+        self.project.delete()
+        self.certifying_organisation.delete()
+        self.training_center.delete()
+        self.course_convener.delete()
+        self.course_type.delete()
+        self.course.delete()
+        self.user.delete()
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def test_AttendeeCreateView_no_login(self):
+        response = self.client.get(reverse('attendee-create', kwargs={
+            'project_slug': self.project.slug,
+            'organisation_slug': self.certifying_organisation.slug,
+            'slug': self.course.slug
+        }))
+        self.assertEqual(response.status_code, 302)
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def test_AttendeeCreateView_with_login(self):
+        status = self.client.login(username='anita', password='password')
+        self.assertTrue(status)
+        url = reverse('attendee-create', kwargs={
+            'project_slug': self.project.slug,
+            'organisation_slug': self.certifying_organisation.slug,
+            'slug': self.course.slug
+        })
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+        expected_templates = [
+            'attendee/create.html'
+        ]
+        self.assertEqual(response.template_name, expected_templates)
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def test_AttendeeAndCourseAttendeeCreate_with_login(self):
+        """
+        Test create attendee that automatically create course attendee
+        from this newly created attendee object.
+
+        """
+        self.client.login(username='anita', password='password')
+        post_data = {
+            'firstname': u'Test',
+            'surname': u'Course-Attendee',
+            'email': u'test@test.com',
+            'certifying_organisation': self.certifying_organisation.id,
+            'add_to_course': True,
+        }
+        response = self.client.post(reverse('attendee-create', kwargs={
+            'project_slug': self.project.slug,
+            'organisation_slug': self.certifying_organisation.slug,
+            'slug': self.course.slug
+        }), post_data)
+        self.assertRedirects(
+            response,
+            reverse(
+                'course-detail',
+                kwargs={
+                    'project_slug': self.project.slug,
+                    'organisation_slug': self.certifying_organisation.slug,
+                    'slug': self.course.slug
+                }))
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def test_AttendeeOnlyCreate_with_login(self):
+        """
+        Test create attendee only.
+
+        """
+        self.client.login(username='anita', password='password')
+        post_data = {
+            'firstname': u'Test',
+            'surname': u'Attendee',
+            'email': u'test@test.com',
+            'certifying_organisation': self.certifying_organisation.id,
+        }
+        response = self.client.post(reverse('attendee-create', kwargs={
+            'project_slug': self.project.slug,
+            'organisation_slug': self.certifying_organisation.slug,
+            'slug': self.course.slug
+        }), post_data)
+        self.assertRedirects(
+            response,
+            reverse(
+                'courseattendee-create',
+                kwargs={
+                    'project_slug': self.project.slug,
+                    'organisation_slug': self.certifying_organisation.slug,
+                    'slug': self.course.slug
+                }))