class TestAdmissionForm(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.current_academic_year = create_current_academic_year()
        cls.education_group = EducationGroupFactory()
        EducationGroupYearFactory(education_group=cls.education_group,
                                  academic_year=cls.current_academic_year)
        cls.formation = ContinuingEducationTrainingFactory(
            education_group=cls.education_group)
        cls.training_manager = ContinuingEducationTrainingManagerFactory(
            training=cls.formation)
        cls.manager = ContinuingEducationManagerFactory()

    def setUp(self):
        self.client.force_login(self.training_manager.person.user)
        self.admission = AdmissionFactory(
            formation=self.formation, academic_year=self.current_academic_year)
        self.data = self.admission.__dict__
        self.data['formation'] = self.admission.formation.pk
        self.data['academic_year'] = self.admission.academic_year.pk

    def test_valid_form_for_managers(self):
        self.client.force_login(self.manager.person.user)
        form = AdmissionForm(data=self.data, user=self.manager.person.user)
        self.assertTrue(form.is_valid(), form.errors)

    def test_valid_form_for_training_managers(self):
        form = AdmissionForm(data=self.data,
                             user=self.training_manager.person.user)
        self.assertTrue(form.is_valid(), form.errors)

    def test_not_valid_wrong_phone_format(self):
        wrong_numbers = [
            '1234567891', '00+32474945669', '0+32474123456', '(32)1234567891',
            '0474.12.34.56', '0474 123456'
        ]
        short_numbers = ['0032123', '+321234', '0123456']
        long_numbers = [
            '003212345678912456', '+3212345678912345', '01234567891234567'
        ]
        self.data['phone_mobile'] = random.choice(wrong_numbers +
                                                  short_numbers + long_numbers)
        form = AdmissionForm(data=self.data,
                             user=self.training_manager.person.user)
        self.assertFalse(form.is_valid(), form.errors)
        self.assertDictEqual(
            form.errors, {
                'phone_mobile': [
                    _("Phone number must start with 0 or 00 or '+' followed by at least "
                      "7 digits and up to 15 digits.")
                ],
            })

    def test_participant_required_fields(self):
        self.client.force_login(self.manager.person.user)
        form = AdmissionForm(data=self.data, user=self.manager.person.user)
        admission_participant_required_fields = [
            'citizenship',
            'phone_mobile',
            'high_school_diploma',
            'last_degree_level',
            'last_degree_field',
            'last_degree_institution',
            'last_degree_graduation_year',
            'professional_status',
            'current_occupation',
            'current_employer',
            'activity_sector',
            'motivation',
            'professional_personal_interests',
            'formation',
            'email',
        ]
        for required_field in admission_participant_required_fields:
            with self.subTest(required_field=required_field):
                self.assertEqual(
                    form.fields[required_field].widget.attrs['class'],
                    'participant_required')

    def test_manager_email_field_required(self):
        self.client.force_login(self.manager.person.user)
        form = AdmissionForm(data=self.data, user=self.manager.person.user)
        self.assertTrue(form.fields['email'].required)

    def test_academic_year_field_required(self):
        self.client.force_login(self.manager.person.user)
        for state in [
                ACCEPTED, ACCEPTED_NO_REGISTRATION_REQUIRED,
                REGISTRATION_SUBMITTED, VALIDATED
        ]:
            with self.subTest(state=state):
                self.admission.state = state
                self.admission.save()
                form = AdmissionForm(data=self.data,
                                     user=self.manager.person.user,
                                     instance=self.admission)
                self.assertTrue(form.fields['academic_year'].required)

    def test_academic_year_field_not_required(self):
        self.client.force_login(self.manager.person.user)
        for state in [
                REJECTED, WAITING, DRAFT, SUBMITTED, CANCELLED,
                CANCELLED_NO_REGISTRATION_REQUIRED
        ]:
            with self.subTest(state=state):
                self.admission.state = state
                self.admission.save()
                form = AdmissionForm(data=self.data,
                                     user=self.manager.person.user,
                                     instance=self.admission)
                self.assertFalse(form.fields['academic_year'].required)
class PrepareJSONTestCase(TestCase):
    def setUp(self):
        self.admission = AdmissionFactory()
        EducationGroupYearFactory(
            education_group=self.admission.formation.education_group,
            academic_year=create_current_academic_year()
        )

    def test_get_json_for_epc(self):
        result = get_json_for_epc(self.admission)
        expected_result = {
            'name': self.admission.person_information.person.last_name,
            'first_name': self.admission.person_information.person.first_name,
            'birth_date': self.admission.person_information.birth_date.strftime("%d/%m/%Y"),
            'birth_location': self.admission.person_information.birth_location,
            'birth_country_iso_code': self.admission.person_information.birth_country.iso_code,
            'sex': "M" if self.admission.person_information.person.gender == "H" else "F",
            'civil_state': self.admission.marital_status,
            'nationality_iso_code': self.admission.citizenship.iso_code,
            'mobile_number': self.admission.phone_mobile,
            'telephone_number': self.admission.residence_phone,
            'private_email': self.admission.email,
            'private_address': {
                'street': self.admission.address.location,
                'locality': self.admission.address.city,
                'postal_code': self.admission.address.postal_code,
                'country_name': self.admission.address.country.name,
                'country_iso_code': self.admission.address.country.iso_code
            },
            'staying_address': {
                'street': self.admission.residence_address.location,
                'locality': self.admission.residence_address.city,
                'postal_code': self.admission.residence_address.postal_code,
                'country_name': self.admission.residence_address.country.name,
                'country_iso_code': self.admission.residence_address.country.iso_code
            },
            'national_registry_number': self.admission.national_registry_number,
            'id_card_number': self.admission.id_card_number,
            'passport_number': self.admission.passport_number,
            'formation_code': self.admission.formation.acronym,
            'formation_academic_year': str(self.admission.academic_year.year),
            'student_case_uuid': str(self.admission.uuid)
        }
        self.assertDictEqual(result, expected_result)

    def test_get_json_for_epc_same_address(self):
        self.admission.residence_address = self.admission.address
        self.admission.save()
        result = get_json_for_epc(self.admission)
        expected_result = {
            'name': self.admission.person_information.person.last_name,
            'first_name': self.admission.person_information.person.first_name,
            'birth_date': self.admission.person_information.birth_date.strftime("%d/%m/%Y"),
            'birth_location': self.admission.person_information.birth_location,
            'birth_country_iso_code': self.admission.person_information.birth_country.iso_code,
            'sex': "M" if self.admission.person_information.person.gender == "H" else "F",
            'civil_state': self.admission.marital_status,
            'nationality_iso_code': self.admission.citizenship.iso_code,
            'mobile_number': self.admission.phone_mobile,
            'telephone_number': self.admission.residence_phone,
            'private_email': self.admission.email,
            'private_address': {
                'street': self.admission.address.location,
                'locality': self.admission.address.city,
                'postal_code': self.admission.address.postal_code,
                'country_name': self.admission.address.country.name,
                'country_iso_code': self.admission.address.country.iso_code
            },
            'staying_address': {},
            'national_registry_number': self.admission.national_registry_number,
            'id_card_number': self.admission.id_card_number,
            'passport_number': self.admission.passport_number,
            'formation_code': self.admission.formation.acronym,
            'formation_academic_year': str(self.admission.academic_year.year),
            'student_case_uuid': str(self.admission.uuid)
        }
        self.assertDictEqual(result, expected_result)

    def test_format_address_for_json(self):
        result = format_address_for_json(self.admission.address)
        expected_result = {
            'street': self.admission.address.location,
            'locality': self.admission.address.city,
            'postal_code': self.admission.address.postal_code,
            'country_name': self.admission.address.country.name,
            'country_iso_code': self.admission.address.country.iso_code
        }
        self.assertDictEqual(result, expected_result)

    def test_format_address_for_json_if_no_address(self):
        result = format_address_for_json(None)
        expected_result = {
            'street': '',
            'locality': '',
            'postal_code': '',
            'country_name': '',
            'country_iso_code': ''
        }
        self.assertDictEqual(result, expected_result)

    def test_format_address_for_json_if_no_country(self):
        self.admission.address.country = None
        self.admission.address.save()
        result = format_address_for_json(self.admission.address)
        expected_result = {
            'street': self.admission.address.location,
            'locality': self.admission.address.city,
            'postal_code': self.admission.address.postal_code,
            'country_name': '',
            'country_iso_code': ''
        }
        self.assertDictEqual(result, expected_result)
Beispiel #3
0
class SendEmailTest(TestCase):
    def setUp(self):
        ed = EducationGroupFactory()
        EducationGroupYearFactory(education_group=ed,
                                  academic_year=create_current_academic_year())
        cet = ContinuingEducationTrainingFactory(education_group=ed)
        self.manager = ContinuingEducationTrainingManagerFactory(training=cet)
        self.other_manager = ContinuingEducationTrainingManagerFactory(
            person=PersonFactory(last_name="BBB"), training=cet)
        self.admission = AdmissionFactory(formation=cet)
        uploaded_file = SimpleUploadedFile(name='upload_test.pdf',
                                           content=str.encode('content'),
                                           content_type="application/pdf")

        self.admission_file = AdmissionFileFactory(
            admission=self.admission,
            path=uploaded_file,
        )

    @patch('continuing_education.business.admission.send_email')
    def test_send_state_changed_email(self, mock_send):
        self.admission.state = admission_state_choices.ACCEPTED
        self.admission._original_state = self.admission.state
        self.admission.save()
        admission.save_state_changed_and_send_email(self.admission)
        args = mock_send.call_args[1]

        self.assertEqual(_(self.admission.state),
                         args.get('data').get('subject').get('state'))
        self.assertEqual(_get_managers_mails(self.admission.formation),
                         args.get('data').get('template').get('mails'))
        self.assertEqual(self.admission.person_information.person.first_name,
                         args.get('data').get('template').get('first_name'))
        self.assertEqual(self.admission.person_information.person.last_name,
                         args.get('data').get('template').get('last_name'))
        self.assertEqual(self.admission.formation,
                         args.get('data').get('template').get('formation'))
        self.assertEqual(_(self.admission.state),
                         args.get('data').get('template').get('state'))
        self.assertEqual(
            self.admission.state_reason
            if self.admission.state_reason else "-",
            args.get('data').get('template').get('reason'))
        self.assertEqual(len(args.get('receivers')), 2)
        self.assertIsNone(args.get('attachment'))

    @patch('continuing_education.business.admission.send_email')
    def test_send_submission_email_to_admin(self, mock_send):
        admission.send_submission_email_to_admission_managers(
            self.admission, connected_user=None)
        args = mock_send.call_args[1]
        self.assertEqual(_(self.admission.formation.acronym),
                         args.get('data').get('subject').get('formation'))
        self.assertEqual(self.admission.person_information.person.first_name,
                         args.get('data').get('template').get('first_name'))
        self.assertEqual(self.admission.person_information.person.last_name,
                         args.get('data').get('template').get('last_name'))
        self.assertEqual(self.admission.formation,
                         args.get('data').get('template').get('formation'))
        self.assertEqual(_(self.admission.state),
                         args.get('data').get('template').get('state'))
        relative_path = reverse('admission_detail',
                                kwargs={'admission_id': self.admission.id})
        url = 'https://{}{}'.format(Site.objects.get_current().domain,
                                    relative_path)
        self.assertEqual(
            url,
            args.get('data').get('template').get('formation_link'))
        self.assertEqual(len(args.get('receivers')), 2)
        self.assertIsNone(args.get('attachment'))

    @patch('continuing_education.business.admission.send_email')
    def test_send_admission_submitted_email_to_participant(self, mock_send):
        admission.send_submission_email_to_participant(self.admission,
                                                       connected_user=None)
        args = mock_send.call_args[1]

        self.assertEqual({}, args.get('data').get('subject'))
        self.assertEqual(_get_managers_mails(self.admission.formation),
                         args.get('data').get('template').get('mails'))
        self.assertEqual(self.admission.formation.title,
                         args.get('data').get('template').get('formation'))
        self.assertEqual(self.admission.person_information.person.last_name,
                         args.get('data').get('template').get('name'))
        self.assertEqual(
            _get_formatted_admission_data(self.admission),
            args.get('data').get('template').get('admission_data'))
        self.assertEqual(len(args.get('receivers')), 2)
        self.assertIsNone(args.get('attachment'))

    @patch('continuing_education.business.admission.send_email')
    def test_send_invoice_uploaded_email(self, mock_send):
        admission.send_invoice_uploaded_email(self.admission)
        args = mock_send.call_args[1]

        self.assertEqual({}, args.get('data').get('subject'))
        self.assertEqual(_get_managers_mails(self.admission.formation),
                         args.get('data').get('template').get('mails'))
        self.assertEqual(self.admission.formation.acronym,
                         args.get('data').get('template').get('formation'))
        self.assertEqual(len(args.get('receivers')), 2)
        self.assertIsNone(args.get('attachment'))

    def test_get_attachments_with_attachment_size_nok(self):
        max_size_to_check = self.admission_file.size - 1
        self.assertIsNone(
            _get_attachments(self.admission.id, max_size_to_check))

    def test_get_attachments_with_attachment_size_ok(self):
        max_size_to_check = self.admission_file.size + 1
        self.assertEqual(
            len(_get_attachments(self.admission.id, max_size_to_check)), 1)

    def test_get_attachments_without_attachment(self):
        max_size_to_check = self.admission_file.size - 1
        AdmissionFile.objects.all().delete()
        self.assertListEqual(
            _get_attachments(self.admission.id, max_size_to_check), [])

    @patch('continuing_education.business.admission.send_email')
    def test_send_admission_accepted_with_condition(self, mock_send):
        self.admission.state = admission_state_choices.ACCEPTED
        self.admission._original_state = self.admission.state
        self.admission.condition_of_acceptance = 'CONDITION'
        self.admission.save()
        admission.save_state_changed_and_send_email(self.admission)
        args = mock_send.call_args[1]

        self.assertEqual(
            self.admission.condition_of_acceptance,
            args.get('data').get('template').get('condition_of_acceptance'))
        self.assertEqual(len(args.get('receivers')), 2)

    @patch('continuing_education.business.admission.send_email')
    def test_send_admission_with_no_registration_required(self, mock_send):
        self.admission.state = admission_state_choices.ACCEPTED
        self.admission._original_state = self.admission.state
        self.admission.formation.registration_required = False
        self.admission.condition_of_acceptance = 'CONDITION'
        self.admission.formation.save()
        self.admission.save()
        admission.save_state_changed_and_send_email(self.admission)
        args = mock_send.call_args[1]

        self.assertEqual(
            self.admission.formation.registration_required,
            args.get('data').get('template').get('registration_required'))
        self.assertEqual(
            self.admission.condition_of_acceptance,
            args.get('data').get('template').get('condition_of_acceptance'))
        self.assertEqual(len(args.get('receivers')), 2)

    def test_build_participant_receivers_2_different_emails(self):
        receivers = _build_participant_receivers(self.admission)
        excepted_receivers = [
            message_config.create_receiver(
                self.admission.person_information.person.id, mail, None)
            for mail in [
                self.admission.email,
                self.admission.person_information.person.email
            ]
        ]
        self.assertCountEqual(receivers, excepted_receivers)

    def test_build_participant_receivers_1_unique_email(self):
        self.admission.email = self.admission.person_information.person.email
        self.admission.save()
        receivers = _build_participant_receivers(self.admission)
        excepted_receivers = [
            message_config.create_receiver(
                self.admission.person_information.person.id,
                self.admission.email, None)
        ]
        self.assertCountEqual(receivers, excepted_receivers)
class UploadFileTestCase(TestCase):
    def setUp(self):
        self.academic_year = create_current_academic_year()
        self.education_group = EducationGroupFactory()
        EducationGroupYearFactory(
            education_group=self.education_group,
            academic_year=self.academic_year
        )
        self.formation = ContinuingEducationTrainingFactory(
            education_group=self.education_group
        )

        self.manager = ContinuingEducationManagerFactory()
        self.client.force_login(self.manager.person.user)
        self.admission = AdmissionFactory(
            formation=self.formation,
            state=SUBMITTED
        )
        self.admission_file = SimpleUploadedFile(
            name='upload_test.pdf',
            content=str.encode(FILE_CONTENT),
            content_type="application/pdf",
        )

    def test_upload_file(self):
        url = reverse('admission_detail', args=[self.admission.pk])
        response = self.client.post(
            url,
            data={
                'myfile': self.admission_file,
                'file_category': file_category_choices.DOCUMENT,
            },
            format='multipart'
        )

        self.assertEqual(AdmissionFile.objects.get(name=self.admission_file.name).uploaded_by, self.manager.person)
        self.assertRedirects(response, reverse('admission_detail', args=[self.admission.id]) + '#documents')
        messages_list = list(messages.get_messages(response.wsgi_request))
        self.assertEqual(response.status_code, 302)
        self.assertIn(
            gettext(_("The document is uploaded correctly")),
            str(messages_list[0])
        )

    @patch('continuing_education.business.admission.send_email')
    def test_upload_file_invoice_email_notification(self, mock_send_mail):
        self.admission.state = admission_state_choices.ACCEPTED
        self.admission.save()
        url = reverse('admission_detail', args=[self.admission.pk])
        response = self.client.post(
            url,
            data={
                'myfile': self.admission_file,
                'file_category': file_category_choices.INVOICE,
                'notify_participant': True
            },
            format='multipart'
        )
        self.assertEqual(AdmissionFile.objects.get(name=self.admission_file.name).uploaded_by, self.manager.person)
        self.assertRedirects(response, reverse('admission_detail', args=[self.admission.id]) + '#documents')
        messages_list = [str(msg) for msg in list(messages.get_messages(response.wsgi_request))]
        self.assertEqual(response.status_code, 302)
        self.assertIn(
            gettext(_("The document is uploaded correctly")),
            messages_list
        )
        self.assertIn(
            gettext(_("A notification email has been sent to the participant")),
            messages_list
        )
        self.assertTrue(mock_send_mail.called)

    @patch('django.db.models.base.Model.save', side_effect=Exception)
    def test_upload_file_error(self, mock_save):
        url = reverse('admission_detail', args=[self.admission.pk])
        response = self.client.post(
            url,
            data={
                'myfile': self.admission_file,
                'file_category': file_category_choices.DOCUMENT,
            },
            format='multipart'
        )

        self.assertRedirects(response, reverse('admission_detail', args=[self.admission.id]) + '#documents')
        messages_list = list(messages.get_messages(response.wsgi_request))
        self.assertEqual(response.status_code, 302)
        self.assertIn(
            gettext(_("A problem occured : the document is not uploaded")),
            str(messages_list[0])
        )

    def test_upload_file_error_name_too_long(self):
        file_name_too_long = SimpleUploadedFile(
            name='{}.pdf'.format(factory.fuzzy.FuzzyText(length=MAX_ADMISSION_FILE_NAME_LENGTH + 10).fuzz()),
            content=str.encode(FILE_CONTENT),
            content_type="application/pdf"
        )

        url = reverse('admission_detail', args=[self.admission.pk])
        response = self.client.post(
            url,
            data={
                'myfile': file_name_too_long,
                'file_category': file_category_choices.DOCUMENT,
            },
            format='multipart'
        )

        self.assertRedirects(response, reverse('admission_detail', args=[self.admission.id]) + '#documents')
        messages_list = list(messages.get_messages(response.wsgi_request))
        self.assertEqual(response.status_code, 302)
        self.assertIn(
            _("The name of the file is too long : maximum %(length)s characters.") % {
                'length': MAX_ADMISSION_FILE_NAME_LENGTH
            },
            str(messages_list[0])
        )

    def test_upload_file_invalid_category(self):
        self.admission.state = admission_state_choices.SUBMITTED
        self.admission.save()
        url = reverse('admission_detail', args=[self.admission.pk])
        response = self.client.post(
            url,
            data={
                'myfile': self.admission_file,
                'file_category': file_category_choices.INVOICE,
            },
            format='multipart'
        )

        self.assertRedirects(response, reverse('admission_detail', args=[self.admission.id]) + '#documents')
        messages_list = list(messages.get_messages(response.wsgi_request))
        self.assertEqual(response.status_code, 302)
        self.assertIn(
            gettext(_("The status of the admission must be Accepted to upload an invoice.")),
            str(messages_list[0])
        )

    def test_upload_file_unallowed_extension(self):
        file_extension = "xyz"
        self.admission_file.name = "{}.{}".format(self.admission_file.name, file_extension)
        url = reverse('admission_detail', args=[self.admission.pk])
        response = self.client.post(
            url,
            data={
                'myfile': self.admission_file,
                'file_category': file_category_choices.DOCUMENT,
            },
            format='multipart'
        )
        self.assertRedirects(response, reverse('admission_detail', args=[self.admission.id]) + '#documents')
        messages_list = list(messages.get_messages(response.wsgi_request))
        self.assertEqual(response.status_code, 302)
        self.assertIn(
            gettext(
                _(
                    "File extension '%(extension)s' is not allowed. "
                    "Allowed extensions are: '%(allowed_extensions)s'."
                ) % {
                    "extension": file_extension,
                    "allowed_extensions": ", ".join(ALLOWED_EXTENSIONS)
                    }
                ),
            str(messages_list[0])
        )

    def test_upload_too_many_files(self):
        admission_files = [
            SimpleUploadedFile(name='file_{}.pdf'.format(i), content=b'test')
            for i in range(0, MAX_ADMISSION_FILES_COUNT+1)
        ]
        url = reverse('admission_detail', args=[self.admission.pk])
        response = {}
        for file in admission_files:
            response = self.client.post(
                url,
                data={
                    'myfile': file,
                    'file_category': file_category_choices.DOCUMENT,
                },
                format='multipart'
            )
        self.assertRedirects(response, reverse('admission_detail', args=[self.admission.id]) + '#documents')
        messages_list = list(messages.get_messages(response.wsgi_request))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            _("The maximum number of files has been reached : maximum %(max)s files allowed.") % {
                'max': MAX_ADMISSION_FILES_COUNT
            }, str(messages_list[-1])
        )