class TestTutorApplicationEpc(TestCase): def setUp(self): self.academic_year = AcademicYearFactory(year=2017) external_id = tutor_application_osis.LEARNING_CONTAINER_YEAR_PREFIX_EXTERNAL_ID + '35654987_2017' self.lbir1200 = LearningContainerYearFactory(academic_year=self.academic_year, acronym="LBIR1200", external_id=external_id) self.lagro2630 = LearningContainerYearFactory(academic_year=self.academic_year, acronym="LAGRO2630") self.bio = LearningContainerYearFactory(academic_year=self.academic_year, acronym="BIO5213") # Creation Person/Tutor Group.objects.create(name="tutors") person = PersonFactory(global_id="98363454") external_id = tutor_application_osis.TUTOR_PREFIX_EXTERNAL_ID + '2089590559' self.tutor = TutorFactory(external_id=external_id, person=person) # Create two tutor applications applications = [_get_application_example(self.lbir1200, '30.5', '40.5'), _get_application_example(self.lagro2630, '12.5', '10.5'), _get_application_example(self.bio, '10.5', '9.5')] self.attribution_new = AttributionNewFactory( global_id=person.global_id, applications=applications ) def test_process_message_update_operation(self): person = self.tutor.person _set_all_application_in_pending_state(self.attribution_new.applications) self.attribution_new.save() self.assertEqual(len(self.attribution_new.applications), 3) self.assertEqual(self.attribution_new.applications[0]['pending'], tutor_application_osis.UPDATE_OPERATION) self.assertEqual(self.attribution_new.applications[1]['pending'], tutor_application_osis.UPDATE_OPERATION) body = [{ 'global_id': person.global_id, 'tutor_applications': [{ 'acronym': 'LBIR1200', 'year': self.academic_year.year, 'charge_lecturing_asked': '0', 'charge_practical_asked': '0', 'last_changed': "2020-12-08 09:58:57+00:00" }] }] body_encoded = bytearray(json.dumps(body), "utf-8") tutor_application_osis.process_message(body_encoded) self.attribution_new.refresh_from_db() self.assertEqual(self.attribution_new.applications[0]['charge_lecturing_asked'], '0') def test_process_message_no_update_operation(self): person = self.tutor.person _set_all_application_in_pending_state(self.attribution_new.applications) self.attribution_new.save() self.assertEqual(len(self.attribution_new.applications), 3) self.assertEqual(self.attribution_new.applications[0]['pending'], tutor_application_osis.UPDATE_OPERATION) self.assertEqual(self.attribution_new.applications[1]['pending'], tutor_application_osis.UPDATE_OPERATION) body = [{ 'global_id': person.global_id, 'tutor_applications': [{ 'acronym': 'LAGRO2630', 'year': self.academic_year.year, 'charge_lecturing_asked': '0', 'charge_practical_asked': '0', 'last_changed': "2013-12-08 09:58:57+00:00" }] }] body_encoded = bytearray(json.dumps(body), "utf-8") tutor_application_osis.process_message(body_encoded) self.attribution_new.refresh_from_db() self.assertEqual(self.attribution_new.applications[0]['charge_lecturing_asked'], '12.5') def test_process_message_with_delete_pending(self): person = self.tutor.person _set_all_application_in_pending_delete(self.attribution_new.applications) self.attribution_new.save() self.assertEqual(len(self.attribution_new.applications), 3) body = [{ 'global_id': person.global_id, 'tutor_applications': [{ 'acronym': 'LAGRO2630', 'year': self.academic_year.year, 'charge_lecturing_asked': '0', 'charge_practical_asked': '0', 'last_changed': "2016-12-08 09:58:57+00:00" }] }] body_encoded = bytearray(json.dumps(body), "utf-8") tutor_application_osis.process_message(body_encoded) self.attribution_new.refresh_from_db() self.assertEqual(len(self.attribution_new.applications), 1) self.assertEqual(self.attribution_new.applications[0]['charge_lecturing_asked'], '12.5') def test_process_when_attribution_new_not_exist(self): body = [{ 'global_id': "321654", 'tutor_applications': [{ 'acronym': 'LAGRO2630', 'year': self.academic_year.year, 'charge_lecturing_asked': '0', 'charge_practical_asked': '0', 'last_changed': "2016-12-08 09:58:57+00:00" }] }] self.assertEqual(find_by_global_id("321654"), None) body_encoded = bytearray(json.dumps(body), "utf-8") tutor_application_osis.process_message(body_encoded) self.assertEqual(find_by_global_id("321654").global_id, "321654") def test_process_with_many_change(self): person = self.tutor.person self.assertEqual(len(self.attribution_new.applications), 3) self.attribution_new.applications[0]['pending'] = tutor_application_osis.UPDATE_OPERATION self.attribution_new.applications[1]['pending'] = tutor_application_osis.DELETE_OPERATION self.attribution_new.save() self.attribution_new.refresh_from_db() body = [{ 'global_id': person.global_id, 'tutor_applications': [ {'acronym': 'LAGRO2630', 'year': self.academic_year.year, 'charge_lecturing_asked': '0', 'charge_practical_asked': '0', 'last_changed': "2021-12-08 09:58:57+00:00" }, {'acronym': 'LBIR1200', 'year': self.academic_year.year, 'charge_lecturing_asked': '0', 'charge_practical_asked': '0', 'last_changed': "2013-12-08 09:58:57+00:00" }, {'acronym': 'BIO5213', 'year': self.academic_year.year, 'charge_lecturing_asked': '0', 'charge_practical_asked': '0', 'last_changed': "2013-12-08 09:58:57+00:00"} ] }] body_encoded = bytearray(json.dumps(body), "utf-8") tutor_application_osis.process_message(body_encoded) self.attribution_new.refresh_from_db() self.assertEqual(len(self.attribution_new.applications), 3) self.assertEqual(self.attribution_new.applications[0]['charge_lecturing_asked'], '12.5') self.assertEqual(self.attribution_new.applications[1]['charge_lecturing_asked'], '30.5') self.assertEqual(self.attribution_new.applications[2]['charge_lecturing_asked'], '0')
class TestOnlineApplication(TestCase): def setUp(self): # Create Group tutor Group.objects.create(name="tutors") # Create user user = UserFactory(username="******") person = PersonFactory(global_id="578945612", user=user) self.tutor = TutorFactory(person=person) # Add permission and log into app add_permission(user, "can_access_attribution_application") self.client.force_login(user) # Create current academic year self.current_academic_year = create_current_academic_year() # Create application year # Application is always next year self.application_academic_year = AcademicYearFactory( year=self.current_academic_year.year + 1 ) # Create Event to allow teacher to register start_date = datetime.datetime.today() - datetime.timedelta(days=10) end_date = datetime.datetime.today() + datetime.timedelta(days=15) self.academic_calendar = AcademicCalendarFactory( academic_year=self.current_academic_year, reference=academic_calendar_type.TEACHING_CHARGE_APPLICATION, start_date=start_date, end_date=end_date ) self.agro_entity = EntityFactory() self.agro_entity_version = EntityVersionFactory(entity=self.agro_entity, acronym="AGRO", entity_type='FACULTY', start_date=self.academic_calendar.start_date, end_date=self.academic_calendar.end_date) self.drt_entity = EntityFactory() self.drt_entity_version = EntityVersionFactory(entity=self.drt_entity, acronym="DRT", entity_type='FACULTY', start_date=self.academic_calendar.start_date, end_date=self.academic_calendar.end_date) # Creation context with multiple learning container year self._create_multiple_learning_container_year() self.attribution = AttributionNewFactory( global_id=person.global_id, applications=self._get_default_application_list(), attributions=self._get_default_attribution_list() ) def test_redirection_to_outside_encoding_period(self): # Remove teaching charge application event self.academic_calendar.delete() url = reverse('applications_overview') url_outside = reverse('outside_applications_period') response = self.client.get(url) self.assertRedirects(response, "%s?next=%s" % (url_outside, url)) # Redirection def test_message_outside_encoding_period(self): # Remove teaching charge application event self.academic_calendar.delete() url = reverse('outside_applications_period') response = self.client.get(url) messages = list(response.context['messages']) self.assertEqual(len(messages), 1) self.assertEqual(messages[0].tags, 'warning') self.assertEqual(messages[0].message, _('The period of online application is closed')) def test_applications_overview(self): url = reverse('applications_overview') response = self.client.get(url) self.assertEqual(response.status_code, 200) context = response.context[-1] self.assertEqual(context['a_tutor'], self.tutor) self.assertEqual(context['current_academic_year'], self.current_academic_year) self.assertEqual(context['application_year'], self.application_academic_year) self.assertEqual(len(context['attributions']), 1) self.assertEqual(context['attributions'][0]['acronym'], self.lagro2500_next.acronym) self.assertEqual(len(context['applications']), 1) self.assertEqual(context['applications'][0]['acronym'], self.lagro1600_next.acronym) self.assertEqual(len(context['attributions_about_to_expire']), 1) self.assertEqual(context['attributions_about_to_expire'][0]['acronym'], self.lbir1300_current.acronym) def test_applications_overview_post_method_not_allowed(self): url = reverse('applications_overview') response = self.client.post(url) self.assertEqual(response.status_code, 405) def test_search_vacant_attribution_initial(self): url = reverse('vacant_attributions_search') response = self.client.get(url) self.assertEqual(response.status_code, 200) context = response.context[0] self.assertEqual(context['a_tutor'], self.tutor) self.assertTrue(context['search_form']) self.assertIsNone(context['attributions_vacant']) def test_search_vacant_attribution_post_not_allowed(self): url = reverse('vacant_attributions_search') response = self.client.post(url) self.assertEqual(response.status_code, 405) def test_search_vacant_attribution_search_list(self): url = reverse('vacant_attributions_search') response = self.client.get(url, data={'learning_container_acronym': 'LAGRO'}) self.assertEqual(response.status_code, 200) context = response.context[-1] self.assertEqual(context['a_tutor'], self.tutor) self.assertTrue(context['search_form']) self.assertEqual(len(context['attributions_vacant']), 2) # Check if LAGRO1600 have the boolean already applied self.assertTrue((next(attrib for attrib in context['attributions_vacant'] if attrib.get('acronym') == self.lagro1600_next.acronym and attrib.get('already_applied')), False)) def test_search_vacant_attribution_search_list_by_faculty(self): url = reverse('vacant_attributions_search') response = self.client.get( url, data={ 'learning_container_acronym': 'LAGRO', 'faculty': self.agro_entity_version.id } ) self.assertEqual(response.status_code, 200) context = response.context[-1] self.assertEqual(len(context['attributions_vacant']), 2) def test_search_vacant_attribution_with_declaration_vac_not_allowed(self): # Create container with type_declaration_vacant not in [RESEVED_FOR_INTERNS, OPEN_FOR_EXTERNS] self.lagro1234_current = _create_learning_container_with_components("LAGRO1234", self.current_academic_year) # Creation learning container for next academic year [==> application academic year] self.lagro1234_next = _create_learning_container_with_components\ ("LAGRO1234", self.application_academic_year, 70, 70, type_declaration_vacant=vacant_declaration_type.DO_NOT_ASSIGN) url = reverse('vacant_attributions_search') response = self.client.get(url, data={'learning_container_acronym': 'LAGRO1234'}) self.assertEqual(response.status_code, 200) context = response.context[0] self.assertEqual(context['a_tutor'], self.tutor) self.assertTrue(context['search_form']) self.assertFalse(context['attributions_vacant']) def test_renew_applications(self): url = reverse('renew_applications') post_data = {'learning_container_year_' + self.lbir1300_next.acronym: 'on'} response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) # redirection self.attribution.refresh_from_db() self.assertEqual(len(self.attribution.applications), 2) # Now we have two applications def test_renew_applications_with_bad_learning_container(self): url = reverse('renew_applications') post_data = {'learning_container_year_' + self.lagro2500_next.acronym: 'on'} response = self.client.post(url, data=post_data, follow=True) self.assertEqual(response.status_code, 200) messages = list(response.context['messages']) self.assertEqual(len(messages), 1) self.assertEqual(messages[0].tags, 'error') self.assertEqual(messages[0].message, _('No attribution renewed')) def test_renew_applications_method_not_allowed(self): url = reverse('renew_applications') response = self.client.get(url) self.assertEqual(response.status_code, 405) def test_delete_application(self): url = reverse('delete_tutor_application', kwargs={'learning_container_year_id': self.lagro1600_next.id}) response = self.client.post(url) self.assertEqual(response.status_code, 302) # redirection self.attribution.refresh_from_db() # pending flag must be set to 'deleted' self.assertTrue((next(attrib for attrib in self.attribution.applications if attrib.get('acronym') == self.lagro1600_next.acronym and attrib.get('pending') == tutor_application_epc.DELETE_OPERATION), False)) def test_delete_application_with_wrong_container(self): url = reverse('delete_tutor_application', kwargs={'learning_container_year_id': self.lbir1300_next.id}) response = self.client.post(url) self.assertEqual(response.status_code, 404) # Not found def test_delete_application_method_not_allowed(self): url = reverse('delete_tutor_application', kwargs={'learning_container_year_id': self.lagro1600_next.id}) response = self.client.get(url) self.assertEqual(response.status_code, 405) def test_get_edit_application_form(self): url = reverse('create_or_update_tutor_application', kwargs={'learning_container_year_id': self.lagro1600_next.id}) response = self.client.get(url) self.assertEqual(response.status_code, 200) context = response.context[0] self.assertEqual(context['a_tutor'], self.tutor) self.assertEqual(context['learning_container_year'], self.lagro1600_next) self.assertTrue(context['form']) def test_post_edit_application_form(self): url = reverse('create_or_update_tutor_application', kwargs={'learning_container_year_id': self.lagro1600_next.id}) post_data = _get_application_example(self.lagro1600_next, '54', '7') response = self.client.post(url, data=post_data, follow=True) self.assertEqual(response.status_code, 200) self.attribution.refresh_from_db() self.assertEqual(len(self.attribution.applications), 1) self.assertEqual(self.attribution.applications[0]['charge_lecturing_asked'], '54.0') self.assertEqual(self.attribution.applications[0]['charge_practical_asked'], '7.0') self.assertEqual(self.attribution.applications[0]['pending'], tutor_application_epc.UPDATE_OPERATION) def test_post_edit_application_form_with_empty_value(self): url = reverse('create_or_update_tutor_application', kwargs={'learning_container_year_id': self.lagro1600_next.id}) post_data = _get_application_example(self.lagro1600_next, None, None) response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 200) context = response.context[0] self.assertTrue(context.get('form')) form = context['form'] self.assertTrue(form.errors) # Not valid because not number entered def test_post_edit_application_form_with_empty_lecturing_value(self): url = reverse('create_or_update_tutor_application', kwargs={'learning_container_year_id': self.lagro1600_next.id}) post_data = _get_application_example(self.lagro1600_next, "15", "") response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) self.attribution.refresh_from_db() self.assertEqual(len(self.attribution.applications), 1) self.assertEqual(self.attribution.applications[0]['charge_lecturing_asked'], '15.0') self.assertEqual(self.attribution.applications[0]['charge_practical_asked'], '0.0') self.assertEqual(self.attribution.applications[0]['pending'], tutor_application_epc.UPDATE_OPERATION) def test_post_edit_application_form_with_value_under_zero(self): url = reverse('create_or_update_tutor_application', kwargs={'learning_container_year_id': self.lagro1600_next.id}) post_data = _get_application_example(self.lagro1600_next, '-1', '5') response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 200) context = response.context[0] self.assertTrue(context.get('form')) form = context['form'] self.assertTrue(form.errors) # Not valid because -1 entered def test_post_overview_with_lecturing_and_practical_component_partim(self): lbira2101a_next = _create_learning_container_with_components("LBIRA2101A", self.application_academic_year, volume_lecturing=20, volume_practical_exercices=20, subtype=learning_unit_year_subtypes.PARTIM) lbira2101a_current = _create_learning_container_with_components( "LBIRA2101A", self.current_academic_year, volume_lecturing=20, volume_practical_exercices=20, subtype=learning_unit_year_subtypes.PARTIM) _link_components_and_learning_unit_year_to_container(lbira2101a_current, "LBIRA2101", subtype=learning_unit_year_subtypes.FULL) _link_components_and_learning_unit_year_to_container(lbira2101a_next, "LBIRA2101", subtype=learning_unit_year_subtypes.FULL) self.attribution.delete() self.attribution = AttributionNewFactory( global_id=self.tutor.person.global_id, applications=[_get_application_example(lbira2101a_next, "10", "10")] ) url = reverse('applications_overview') response = self.client.get(url) self.assertEqual(response.status_code, 200) context = response.context[0] self.assertEqual(len(context['applications']), 1) self.assertEqual(context['applications'][0]['acronym'], lbira2101a_next.acronym) with self.assertRaises(KeyError): context['applications'][0]['PRACTICAL_EXERCISES'] with self.assertRaises(KeyError): context['applications'][0]['LECTURING'] def _create_multiple_learning_container_year(self): # Creation learning container for current academic year self.lbir1200_current = _create_learning_container_with_components("LBIR1200", self.current_academic_year) self.lbir1300_current = _create_learning_container_with_components("LBIR1300", self.current_academic_year) self.ldroi1500_current = _create_learning_container_with_components("LDROI1500", self.current_academic_year) # Creation learning container for next academic year [==> application academic year] self.lbir1200_next = _create_learning_container_with_components("LBIR1200", self.application_academic_year, 70, 70) self.lbir1300_next = _create_learning_container_with_components("LBIR1300", self.application_academic_year, 60, 60) self.lagro1600_next = _create_learning_container_with_components("LAGRO1600", self.application_academic_year, 54, 7) self.lagro2500_next = _create_learning_container_with_components("LAGRO2500", self.application_academic_year, 0, 70) self._create_entity_container_yrs() def _get_default_application_list(self): return [ _get_application_example(self.lagro1600_next, '15', '0') ] def _get_default_attribution_list(self): return [ # Attribution in current year _get_attribution_example(self.lbir1200_current, '20.0', '31.5', 2015, 2019), _get_attribution_example(self.lbir1300_current, '21.5', '40', 2015, self.current_academic_year.year), # Attribution in next year _get_attribution_example(self.lagro2500_next, '29', '10', 2015, 2020) ] def _create_entity_container_yrs(self): self.lbir1200_current.allocation_entity = self.agro_entity self.lbir1200_current.save() self.lbir1300_current.allocation_entity = self.agro_entity self.lbir1300_current.save() self.lbir1200_next.allocation_entity = self.agro_entity self.lbir1200_next.save() self.lbir1300_next.allocation_entity = self.agro_entity self.lbir1300_next.save() self.lagro1600_next.allocation_entity = self.agro_entity self.lagro1600_next.save() self.lagro2500_next.allocation_entity = self.agro_entity self.lagro2500_next.save() self.ldroi1500_current.allocation_entity = self.drt_entity self.ldroi1500_current.save()
class TestTutorApplicationEpc(TestCase): def setUp(self): self.academic_year = AcademicYearFactory(year=2017) external_id = tutor_application_epc.LEARNING_CONTAINER_YEAR_PREFIX_EXTERNAL_ID + '35654987_2017' self.lbir1200 = LearningContainerYearFactory(academic_year=self.academic_year, acronym="LBIR1200", external_id=external_id) self.lagro2630 = LearningContainerYearFactory(academic_year=self.academic_year, acronym="LAGRO2630") # Creation Person/Tutor Group.objects.create(name="tutors") person = PersonFactory(global_id="98363454") external_id = tutor_application_epc.TUTOR_PREFIX_EXTERNAL_ID + '2089590559' self.tutor = TutorFactory(external_id=external_id, person=person) # Create two tutor applications applications = [_get_application_example(self.lbir1200, '30.5', '40.5'), _get_application_example(self.lagro2630, '12.5', '0')] self.attribution = AttributionNewFactory( global_id=person.global_id, applications=applications ) def test_extract_learning_container_year_epc_info(self): learning_container_info = tutor_application_epc._extract_learning_container_year_epc_info('LBIR1200', 2017) self.assertIsInstance(learning_container_info, dict) self.assertEqual(learning_container_info['reference'], '35654987') self.assertEqual(learning_container_info['year'], 2017) def test_extract_learning_container_year_epc_info_empty(self): learning_container_info = tutor_application_epc._extract_learning_container_year_epc_info('LBIR1250', 2017) self.assertIsInstance(learning_container_info, dict) self.assertFalse(learning_container_info) def test_extract_learning_container_year_epc_info_with_external_id_empty(self): self.lbir1200.external_id = None self.lbir1200.save() learning_container_info = tutor_application_epc._extract_learning_container_year_epc_info('LBIR1200', 2017) self.assertIsInstance(learning_container_info, dict) self.assertFalse(learning_container_info) def test_convert_to_epc_application(self): person = self.tutor.person application = _get_application_example(self.lbir1200, '30.5', '40.5') epc_message = tutor_application_epc._convert_to_epc_application(application=application) self.assertTrue(epc_message) self.assertEqual(epc_message['remark'], application['remark']) self.assertEqual(epc_message['course_summary'], application['course_summary']) self.assertEqual(epc_message['lecturing_allocation'], application['charge_lecturing_asked']) self.assertEqual(epc_message['practical_allocation'], application['charge_practical_asked']) self.assertIsInstance(epc_message['learning_container_year'], dict) self.assertEqual(epc_message['learning_container_year']['reference'], '35654987') self.assertEqual(epc_message['learning_container_year']['year'], 2017) def test_process_message_delete_operation(self): person = self.tutor.person self.assertEqual(len(self.attribution.applications), 2) body = { 'operation': tutor_application_epc.DELETE_OPERATION, 'global_id': person.global_id, 'learning_container_year': { 'acronym': 'LBIR1200', 'year': 2017 } } body_encoded = bytearray(json.dumps(body), "utf-8") tutor_application_epc.process_message(body_encoded) # Check if the application is removed self.attribution.refresh_from_db() self.assertEqual(len(self.attribution.applications), 1) attribution_left = self.attribution.applications[0] self.assertEqual(attribution_left['acronym'], self.lagro2630.acronym) def test_process_message_update_operation(self): person = self.tutor.person _set_all_application_in_pending_state(self.attribution.applications) self.attribution.save() ## Check if all are in pending self.assertEqual(len(self.attribution.applications), 2) self.assertEqual(self.attribution.applications[0]['pending'], tutor_application_epc.UPDATE_OPERATION) self.assertEqual(self.attribution.applications[1]['pending'], tutor_application_epc.UPDATE_OPERATION) body = { 'operation': tutor_application_epc.UPDATE_OPERATION, 'global_id': person.global_id, 'learning_container_year': { 'acronym': 'LBIR1200', 'year': 2017 } } body_encoded = bytearray(json.dumps(body), "utf-8") tutor_application_epc.process_message(body_encoded) # Check if the application is removed self.attribution.refresh_from_db() applications_not_pending = [application for application in self.attribution.applications if not "pending" in application] self.assertEqual(len(applications_not_pending), 1) def test_process_message_with_error_operation(self): person = self.tutor.person _set_all_application_in_pending_state(self.attribution.applications) self.attribution.save() ## Check if all are in pending self.assertEqual(len(self.attribution.applications), 2) self.assertEqual(self.attribution.applications[0]['pending'], tutor_application_epc.UPDATE_OPERATION) self.assertEqual(self.attribution.applications[1]['pending'], tutor_application_epc.UPDATE_OPERATION) body = { 'operation': tutor_application_epc.UPDATE_OPERATION, 'global_id': person.global_id, 'learning_container_year': { 'acronym': 'LBIR1200', 'year': 2017 }, tutor_application_epc.ERROR_EPC_FIELD: 'An error occured in EPC' } body_encoded = bytearray(json.dumps(body), "utf-8") tutor_application_epc.process_message(body_encoded) # Check if the application is removed self.attribution.refresh_from_db() applications_not_pending = [application for application in self.attribution.applications if not "pending" in application] self.assertEqual(len(applications_not_pending), 0) # No changed