diff --git a/templates/admission/continuing_education/checklist.html b/templates/admission/continuing_education/checklist.html index 646ec1d1d..1eb56f14e 100644 --- a/templates/admission/continuing_education/checklist.html +++ b/templates/admission/continuing_education/checklist.html @@ -292,6 +292,8 @@ }) }); + let onFirstTabLoad = true; + menuItems.on('shown.bs.tab', function (e) { $(this).parents('.list-group-item').find('.sub-items').show(); @@ -303,8 +305,18 @@ refreshDocuments(tabPaneId); - // refresh info viewer (e.target = active && e.relatedTarget = previous) - if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // refresh info viewer + if (onFirstTabLoad) { + onFirstTabLoad = false; + if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // move info from the current tab to the info viewer + $('#infos-shortcut').click(); + } else { + // hide the info viewer + $('#info-viewer-tab').hide(); + } + } else if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // (e.target = active && e.relatedTarget = previous) const $info = $('#info-viewer-tab .info-content'); // move old info from info viewer to old tab const oldTabPanel = $($(e.relatedTarget).parent().attr('href')).find('.info-part'); @@ -341,12 +353,6 @@ // Activate tab from hash on first load $(`#checklist-menu *[data-toggle="tab"][href="${defaultTab}"]`).click(); - if (configurationCache.getItem('side-tab', 'documents') === 'info') { - $('#infos-shortcut').click(); - } else { - $('#info-viewer-tab').hide(); - } - $('textarea[name="comment"]:visible').each(autogrow); }); diff --git a/templates/admission/doctorate/checklist.html b/templates/admission/doctorate/checklist.html index 2904b3217..eb0fbdb50 100644 --- a/templates/admission/doctorate/checklist.html +++ b/templates/admission/doctorate/checklist.html @@ -60,6 +60,7 @@ {% can_update_tab 'person' as can_update_person_tab %} {% can_update_tab 'coordonnees' as can_update_coordonnees_tab %} + {% can_update_tab 'languages' as can_update_languages_tab %} {% can_update_tab 'accounting' as can_update_accounting_tab %} {% can_update_tab 'training-choice' as can_update_training_choice_tab %} {% can_update_tab 'curriculum' as can_update_curriculum %} @@ -90,6 +91,12 @@ {% url base_namespace|add:":training-choice" view.kwargs.uuid as training_choice_url %} {% endif %} + {% if can_update_languages_tab %} + {% url base_namespace|add:":update:languages" view.kwargs.uuid as languages_url %} + {% else %} + {% url base_namespace|add:":languages" view.kwargs.uuid as languages_url %} + {% endif %} + {% concat "#choix_formation" as checklist_training_choice_url %}
{% include 'admission/general_education/includes/checklist/financeabilty_info.html' with current=original_admission.checklist.current.financabilite %} + +
+
+
{% translate 'Knowledge of languages' %}
+ {% concat languages_url next_url as contextual_languages_url %} + {{ ''|edit_button:contextual_languages_url|safe }} +
+
+ {% include 'admission/exports/recap/includes/languages.html' with connaissances_langues=resume_proposition.connaissances_langues %} +
+
{% if can_update_curriculum %} - {% url 'admission:general-education:update:curriculum' view.kwargs.uuid as global_curriculum_update_url %} + {% url 'admission:doctorate:update:curriculum' view.kwargs.uuid as global_curriculum_update_url %} {% endif %} {% multiple_field_data specific_questions_by_tab|get_item:'CURRICULUM' edit_link_button=global_curriculum_update_url|add:next_url %}
@@ -299,7 +317,7 @@ {% else %} {% include 'admission/general_education/includes/checklist/previous_experience_single.html' with current=child authentication_form=authentication_forms|get_item_or_none:child.extra.identifiant experience_authentication_history_entry=all_experience_authentication_history_entries|get_item_or_none:child.extra.identifiant %}
- {% experience_details_template resume_proposition=resume_proposition experience=experience with_edit_link_button=True can_update_curriculum=can_update_curriculum can_update_education=can_update_education specific_questions=specific_questions_by_tab can_delete_curriculum=can_delete_curriculum %} + {% experience_details_template resume_proposition=resume_proposition experience=experience with_edit_link_button=True specific_questions=specific_questions_by_tab %}
{% endif %} {% endwith %} @@ -596,6 +614,8 @@ }) }); + let onFirstTabLoad = true; + menuItems.on('shown.bs.tab', function (e) { $(this).parents('.list-group-item').find('.sub-items').show(); @@ -607,8 +627,18 @@ refreshDocuments(tabPaneId); - // refresh info viewer (e.target = active && e.relatedTarget = previous) - if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // refresh info viewer + if (onFirstTabLoad) { + onFirstTabLoad = false; + if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // move info from the current tab to the info viewer + $('#infos-shortcut').click(); + } else { + // hide the info viewer + $('#info-viewer-tab').hide(); + } + } else if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // (e.target = active && e.relatedTarget = previous) const $info = $('#info-viewer-tab .info-content'); // move old info from info viewer to old tab const oldTabPanel = $($(e.relatedTarget).parent().attr('href')).find('.info-part'); @@ -645,12 +675,6 @@ // Activate tab from hash on first load $(`#checklist-menu *[data-toggle="tab"][href="${defaultTab}"]`).click(); - if (configurationCache.getItem('side-tab', 'documents') === 'info') { - $('#infos-shortcut').click(); - } else { - $('#info-viewer-tab').hide(); - } - $('textarea[name="comment"]:visible').each(autogrow); $('[data-toggle=popover]').popover(); diff --git a/templates/admission/general_education/checklist.html b/templates/admission/general_education/checklist.html index 3a7c47366..ae91225e0 100644 --- a/templates/admission/general_education/checklist.html +++ b/templates/admission/general_education/checklist.html @@ -368,7 +368,7 @@ {% else %} {% include 'admission/general_education/includes/checklist/previous_experience_single.html' with current=child authentication_form=authentication_forms|get_item_or_none:child.extra.identifiant experience_authentication_history_entry=all_experience_authentication_history_entries|get_item_or_none:child.extra.identifiant %}
- {% experience_details_template resume_proposition=resume_proposition experience=experience with_edit_link_button=True can_update_curriculum=can_update_curriculum can_update_education=can_update_education specific_questions=specific_questions_by_tab can_delete_curriculum=can_delete_curriculum %} + {% experience_details_template resume_proposition=resume_proposition experience=experience with_edit_link_button=True specific_questions=specific_questions_by_tab %}
{% endif %} {% endwith %} @@ -693,6 +693,8 @@ }) }); + let onFirstTabLoad = true; + menuItems.on('shown.bs.tab', function (e) { $(this).parents('.list-group-item').find('.sub-items').show(); @@ -704,8 +706,18 @@ refreshDocuments(tabPaneId); - // refresh info viewer (e.target = active && e.relatedTarget = previous) - if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // refresh info viewer + if (onFirstTabLoad) { + onFirstTabLoad = false; + if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // move info from the current tab to the info viewer + $('#infos-shortcut').click(); + } else { + // hide the info viewer + $('#info-viewer-tab').hide(); + } + } else if (configurationCache.getItem('side-tab', 'documents') === 'info') { + // (e.target = active && e.relatedTarget = previous) const $info = $('#info-viewer-tab .info-content'); // move old info from info viewer to old tab const oldTabPanel = $($(e.relatedTarget).parent().attr('href')).find('.info-part'); @@ -742,12 +754,6 @@ // Activate tab from hash on first load $(`#checklist-menu *[data-toggle="tab"][href="${defaultTab}"]`).click(); - if (configurationCache.getItem('side-tab', 'documents') === 'info') { - $('#infos-shortcut').click(); - } else { - $('#info-viewer-tab').hide(); - } - $('textarea[name="comment"]:visible').each(autogrow); $('[data-toggle=popover]').popover(); diff --git a/templatetags/admission.py b/templatetags/admission.py index 19fdd01cb..3ff0047ff 100644 --- a/templatetags/admission.py +++ b/templatetags/admission.py @@ -41,11 +41,6 @@ from django.utils.safestring import SafeString, mark_safe from django.utils.translation import get_language, gettext_lazy as _, pgettext, gettext from osis_comment.models import CommentEntry - -from admission.ddd.admission.doctorat.preparation.domain.model.statut_checklist import ( - INDEX_ONGLETS_CHECKLIST as INDEX_ONGLETS_CHECKLIST_DOCTORALE, -) -from osis_document.api.utils import get_remote_metadata, get_remote_token from osis_history.models import HistoryEntry from rules.templatetags import rules @@ -66,6 +61,9 @@ from admission.ddd.admission.doctorat.preparation.domain.model.enums import ( ChoixStatutPropositionDoctorale, ) +from admission.ddd.admission.doctorat.preparation.domain.model.statut_checklist import ( + INDEX_ONGLETS_CHECKLIST as INDEX_ONGLETS_CHECKLIST_DOCTORALE, +) from admission.ddd.admission.doctorat.validation.domain.model.enums import ChoixSexe from admission.ddd.admission.domain.model.enums.authentification import EtatAuthentificationParcours from admission.ddd.admission.dtos import EtudesSecondairesAdmissionDTO, CoordonneesDTO, IdentificationDTO @@ -126,6 +124,7 @@ from ddd.logic.shared_kernel.campus.dtos import UclouvainCampusDTO from ddd.logic.shared_kernel.profil.dtos.parcours_externe import ExperienceAcademiqueDTO, ExperienceNonAcademiqueDTO from ddd.logic.shared_kernel.profil.dtos.parcours_interne import ExperienceParcoursInterneDTO +from osis_document.api.utils import get_remote_metadata, get_remote_token from osis_role.contrib.permissions import _get_roles_assigned_to_user from osis_role.templatetags.osis_role import has_perm from reference.models.country import Country @@ -334,11 +333,6 @@ def __eq__(self, other): Tab('doctorate-education', _('Course choice'), 'person-chalkboard'): [ Tab('training-choice', _('Course choice')), ], - # TODO Education choice - Tab('experience', _('Previous experience'), 'list-alt'): [ - Tab('curriculum', _('Curriculum')), - Tab('languages', _('Knowledge of languages')), - ], Tab('doctorate', pgettext('tab', 'PhD project'), 'graduation-cap'): [ Tab('project', _('Research project')), Tab('cotutelle', _('Cotutelle')), @@ -1045,7 +1039,8 @@ def checklist_state_button(context, **kwargs): def edit_button(string, url): return ( str(string) - + f'' + + f'' + f'' ) @@ -1342,9 +1337,6 @@ def experience_details_template( specific_questions: Dict[str, List[QuestionSpecifiqueDTO]] = None, with_edit_link_button=True, hide_files=True, - can_update_curriculum=False, - can_update_education=False, - can_delete_curriculum=False, ): """ Return the template used to render the experience details. @@ -1354,9 +1346,6 @@ def experience_details_template( :param specific_questions: The specific questions related to the experience (only used for secondary studies) :param with_edit_link_button: Specify if the edit link button should be displayed :param hide_files: Specify if the files should be hidden - :param can_update_curriculum: Specify if the user can update the curriculum - :param can_update_education: Specify if the user can update the education - :param can_delete_curriculum: Specify if the user can delete an experience from the curriculum :return: The rendered template """ next_url_suffix = f'?next={context.get("request").path}&next_hash_url=parcours_anterieur__{experience.uuid}' @@ -1368,110 +1357,48 @@ def experience_details_template( 'formation': resume_proposition.proposition.formation, 'hide_files': hide_files, 'checklist_display': True, + 'curex_link_button': '', 'edit_link_button': '', 'duplicate_link_button': '', 'delete_link_button': '', 'edit_link_button_in_new_tab': experience.epc_experience, } + if with_edit_link_button: + experience_urls = get_experience_urls( + user=context['request'].user, + admission=context['view'].admission, + experience=experience, + candidate_noma=context['view'].proposition.noma_candidat, + ) + + if experience_urls['curex_url']: + res_context['curex_link_button'] = experience_urls['curex_url'] + + elif experience_urls['edit_url']: + res_context['edit_link_button'] = experience_urls['edit_url'] + next_url_suffix + + if experience_urls['delete_url']: + res_context['delete_link_button'] = experience_urls['delete_url'] + delete_next_url_suffix + + if experience_urls['duplicate_url']: + res_context['duplicate_link_button'] = experience_urls['duplicate_url'] + next_url_suffix + if experience.__class__ == ExperienceAcademiqueDTO: res_context['custom_base_template'] = 'admission/exports/recap/includes/curriculum_educational_experience.html' res_context['title'] = _('Academic experience') res_context['with_single_header_buttons'] = True - - if with_edit_link_button and can_update_curriculum: - if not experience.epc_experience: - res_context['duplicate_link_button'] = ( - reverse( - 'admission:general-education:update:curriculum:educational_duplicate', - args=[resume_proposition.proposition.uuid, experience.uuid], - ) - + next_url_suffix - ) - res_context['edit_link_button'] = ( - reverse( - 'admission:general-education:update:curriculum:educational', - args=[resume_proposition.proposition.uuid, experience.uuid], - ) - + next_url_suffix - ) - if can_delete_curriculum: - res_context['delete_link_button'] = ( - reverse( - 'admission:general-education:update:curriculum:educational_delete', - args=[resume_proposition.proposition.uuid, experience.uuid], - ) - + delete_next_url_suffix - ) - - elif context['admission'].noma_candidat: - res_context['curex_link_button'] = resolve_url( - 'parcours-externe-view', - noma=context['admission'].noma_candidat, - ) - res_context.update(get_educational_experience_context(resume_proposition, experience)) elif experience.__class__ == ExperienceNonAcademiqueDTO: res_context['custom_base_template'] = 'admission/exports/recap/includes/curriculum_professional_experience.html' res_context['title'] = _('Non-academic activity') res_context['with_single_header_buttons'] = True - - if with_edit_link_button and can_update_curriculum: - if not experience.epc_experience: - res_context['edit_link_button'] = ( - reverse( - 'admission:general-education:update:curriculum:non_educational', - args=[resume_proposition.proposition.uuid, experience.uuid], - ) - + next_url_suffix - ) - - if can_delete_curriculum: - res_context['delete_link_button'] = ( - reverse( - 'admission:general-education:update:curriculum:non_educational_delete', - args=[resume_proposition.proposition.uuid, experience.uuid], - ) - + delete_next_url_suffix - ) - - elif context['admission'].noma_candidat: - res_context['edit_link_button'] = resolve_url( - 'edit-experience-non-academique-view', - noma=context['admission'].noma_candidat, - experience_uuid=experience.uuid, - ) - - res_context['duplicate_link_button'] = ( - reverse( - 'admission:general-education:update:curriculum:non_educational_duplicate', - args=[resume_proposition.proposition.uuid, experience.uuid], - ) - + next_url_suffix - ) - res_context.update(get_non_educational_experience_context(experience)) elif experience.__class__ == EtudesSecondairesAdmissionDTO: res_context['custom_base_template'] = 'admission/exports/recap/includes/education.html' res_context['etudes_secondaires'] = experience - - if with_edit_link_button and can_update_education: - if not experience.epc_experience: - res_context['edit_link_button'] = ( - reverse( - 'admission:general-education:update:education', - args=[resume_proposition.proposition.uuid], - ) - ) + next_url_suffix - - elif context['admission'].noma_candidat: - res_context['edit_link_button'] = resolve_url( - 'edit-etudes-secondaires-view', - noma=context['admission'].noma_candidat, - ) - res_context.update( get_secondary_studies_context( resume_proposition, @@ -1496,9 +1423,7 @@ def checklist_experience_action_links_context( parcours_tab_id='', ): next_url_suffix = f'?next={context["request"].path}&next_hash_url={parcours_tab_id}' - base_namespace = context['view'].base_namespace proposition_uuid = context['view'].kwargs['uuid'] - proposition_uuid_str = str(proposition_uuid) result_context = { 'prefix': prefix, @@ -1512,90 +1437,29 @@ def checklist_experience_action_links_context( if experience.__class__ == ExperienceParcoursInterneDTO: return result_context - elif experience.__class__ == EtudesSecondairesAdmissionDTO: - if not experience.epc_experience: - result_context['update_url'] = ( - resolve_url( - f'{base_namespace}:update:education', - uuid=proposition_uuid_str, - ) - + next_url_suffix - ) - elif context['admission'].noma_candidat: - result_context['update_url'] = resolve_url( - 'edit-etudes-secondaires-view', - noma=context['admission'].noma_candidat, - ) elif ( - experience.valorisee_par_admissions + experience.__class__ == EtudesSecondairesAdmissionDTO + or experience.valorisee_par_admissions and proposition_uuid in experience.valorisee_par_admissions and experience.derniere_annee == current_year ): - if experience.__class__ == ExperienceAcademiqueDTO: - if not experience.epc_experience: - result_context['duplicate_url'] = resolve_url( - f'{base_namespace}:update:curriculum:educational_duplicate', - uuid=proposition_uuid_str, - experience_uuid=experience.uuid, - ) - result_context['update_url'] = ( - resolve_url( - f'{base_namespace}:update:curriculum:educational', - uuid=proposition_uuid_str, - experience_uuid=experience.uuid, - ) - + next_url_suffix - ) - - can_delete_curriculum = has_perm(context, 'admission.delete_admission_curriculum') - if can_delete_curriculum: - result_context['delete_url'] = ( - resolve_url( - f'{base_namespace}:update:curriculum:educational_delete', - uuid=proposition_uuid_str, - experience_uuid=experience.uuid, - ) - + next_url_suffix - ) - elif context['admission'].noma_candidat: - result_context['curex_url'] = resolve_url( - 'parcours-externe-view', - noma=context['admission'].noma_candidat, - ) - - elif experience.__class__ == ExperienceNonAcademiqueDTO: - result_context['duplicate_url'] = resolve_url( - f'{base_namespace}:update:curriculum:non_educational_duplicate', - uuid=proposition_uuid_str, - experience_uuid=experience.uuid, - ) + experience_urls = get_experience_urls( + user=context['request'].user, + admission=context['view'].admission, + experience=experience, + candidate_noma=context['view'].proposition.noma_candidat, + ) + + if experience_urls['curex_url']: + result_context['curex_url'] = experience_urls['curex_url'] + + elif experience_urls['edit_url']: + result_context['update_url'] = experience_urls['edit_url'] + next_url_suffix + + if experience_urls['delete_url']: + result_context['delete_url'] = experience_urls['delete_url'] + next_url_suffix - if not experience.epc_experience: - result_context['update_url'] = ( - resolve_url( - f'{base_namespace}:update:curriculum:non_educational', - uuid=proposition_uuid_str, - experience_uuid=experience.uuid, - ) - + next_url_suffix - ) - - can_delete_curriculum = has_perm(context, 'admission.delete_admission_curriculum') - if can_delete_curriculum: - result_context['delete_url'] = ( - resolve_url( - f'{base_namespace}:update:curriculum:non_educational_delete', - uuid=proposition_uuid_str, - experience_uuid=experience.uuid, - ) - + next_url_suffix - ) - elif context['admission'].noma_candidat: - result_context['update_url'] = resolve_url( - 'edit-experience-non-academique-view', - noma=context['admission'].noma_candidat, - experience_uuid=experience.uuid, - ) + result_context['duplicate_url'] = experience_urls['duplicate_url'] return result_context diff --git a/tests/templatetags/test_admission.py b/tests/templatetags/test_admission.py index 51efba86e..e959a056c 100644 --- a/tests/templatetags/test_admission.py +++ b/tests/templatetags/test_admission.py @@ -24,7 +24,6 @@ # # ############################################################################## import datetime -import unittest import uuid from unittest.mock import Mock, patch, MagicMock @@ -100,6 +99,7 @@ ) from admission.tests.factories import DoctorateAdmissionFactory from admission.tests.factories.continuing_education import ContinuingEducationAdmissionFactory +from admission.tests.factories.general_education import GeneralEducationAdmissionFactory from base.forms.utils.file_field import PDF_MIME_TYPE from base.models.entity_version import EntityVersion from base.models.enums.education_group_types import TrainingType @@ -545,7 +545,8 @@ def test_get_item_or_none(self): self.assertEqual(get_item_or_none(dictionary, 'b'), None) def test_experience_details_template_with_an_educational_experience(self): - proposition_uuid = uuid.uuid4() + general_admission = GeneralEducationAdmissionFactory() + proposition_uuid = general_admission.uuid experience = ExperienceAcademiqueDTOFactory( pays=BE_ISO_CODE, regime_linguistique=FR_ISO_CODE, @@ -553,10 +554,30 @@ def test_experience_details_template_with_an_educational_experience(self): annees=[AnneeExperienceAcademiqueDTOFactory(uuid=uuid.uuid4())], ) + perms = { + 'admission.change_admission_curriculum': True, + 'admission.change_admission_secondary_studies': True, + 'admission.delete_admission_curriculum': True, + 'profil.can_edit_parcours_externe': True, + 'profil.can_see_parcours_externe': True, + } + kwargs = { 'context': { - 'request': Mock(path='mypath'), - 'admission': MagicMock(noma_candidat='0123456'), + 'request': Mock( + path='mypath', + user=MagicMock( + _computed_permissions=perms, + ), + ), + 'view': MagicMock( + admission=general_admission, + proposition=MagicMock( + uuid=proposition_uuid, + noma_candidat='0123456', + formation=MagicMock(), + ), + ), }, 'resume_proposition': MagicMock( est_proposition_generale=True, @@ -568,8 +589,6 @@ def test_experience_details_template_with_an_educational_experience(self): ), ), 'experience': experience, - 'can_update_curriculum': True, - 'can_delete_curriculum': True, } template_params = experience_details_template(**kwargs) @@ -579,6 +598,7 @@ def test_experience_details_template_with_an_educational_experience(self): 'admission/exports/recap/includes/curriculum_educational_experience.html', ) self.assertEqual(template_params['title'], _('Academic experience')) + self.assertEqual(template_params['curex_link_button'], '') self.assertEqual( template_params['edit_link_button'], '/admissions/general-education/{proposition_uuid}/update/curriculum/educational/{experience_uuid}' @@ -611,14 +631,14 @@ def test_experience_details_template_with_an_educational_experience(self): self.assertEqual(template_params['evaluation_system_with_credits'], True) # Without the right to delete an experience - kwargs['can_delete_curriculum'] = False + perms['admission.delete_admission_curriculum'] = False template_params = experience_details_template(**kwargs) self.assertEqual(template_params['delete_link_button'], '') - kwargs['can_delete_curriculum'] = True + perms['admission.delete_admission_curriculum'] = True - # With a valuated experience + # With an EPC experience kwargs['experience'] = ExperienceAcademiqueDTOFactory( pays=BE_ISO_CODE, regime_linguistique=FR_ISO_CODE, @@ -635,10 +655,38 @@ def test_experience_details_template_with_an_educational_experience(self): noma='0123456', ), ) + self.assertEqual(template_params['edit_link_button'], '') + self.assertEqual(template_params['duplicate_link_button'], '') + self.assertEqual(template_params['delete_link_button'], '') + + # Without the right to see the experience from the profile + perms['profil.can_see_parcours_externe'] = False + template_params = experience_details_template(**kwargs) + + self.assertEqual(template_params['curex_link_button'], '') + self.assertEqual( + template_params['edit_link_button'], + '/osis_profile/{noma}/parcours_externe/edit/experience_academique/{annee_experience_uuid}' + '?next=mypath&next_hash_url=parcours_anterieur__{experience_uuid}'.format( + noma='0123456', + annee_experience_uuid=kwargs['experience'].annees[0].uuid, + experience_uuid=kwargs['experience'].uuid, + ), + ) + self.assertEqual(template_params['duplicate_link_button'], '') + self.assertEqual(template_params['delete_link_button'], '') + + # Without the right to update the experience from the profile + perms['profil.can_edit_parcours_externe'] = False + template_params = experience_details_template(**kwargs) + + self.assertEqual(template_params['curex_link_button'], '') + self.assertEqual(template_params['edit_link_button'], '') + self.assertEqual(template_params['duplicate_link_button'], '') self.assertEqual(template_params['delete_link_button'], '') # Without the right to update education - kwargs['can_update_curriculum'] = False + perms['admission.change_admission_curriculum'] = False template_params = experience_details_template(**kwargs) @@ -647,13 +695,34 @@ def test_experience_details_template_with_an_educational_experience(self): self.assertEqual(template_params['delete_link_button'], '') def test_experience_details_with_a_non_educational_experience(self): - proposition_uuid = uuid.uuid4() + general_admission = GeneralEducationAdmissionFactory() + proposition_uuid = general_admission.uuid experience = ExperienceNonAcademiqueDTOFactory() + perms = { + 'admission.change_admission_curriculum': True, + 'admission.change_admission_secondary_studies': True, + 'admission.delete_admission_curriculum': True, + 'profil.can_edit_parcours_externe': True, + 'profil.can_see_parcours_externe': True, + } + kwargs = { 'context': { - 'request': Mock(path='mypath'), - 'admission': MagicMock(noma_candidat='0123456'), + 'request': Mock( + path='mypath', + user=MagicMock( + _computed_permissions=perms, + ), + ), + 'view': MagicMock( + admission=general_admission, + proposition=MagicMock( + uuid=proposition_uuid, + noma_candidat='0123456', + formation=MagicMock(), + ), + ), }, 'resume_proposition': MagicMock( est_proposition_generale=True, @@ -665,8 +734,6 @@ def test_experience_details_with_a_non_educational_experience(self): ), ), 'experience': experience, - 'can_update_curriculum': True, - 'can_delete_curriculum': True, } template_params = experience_details_template(**kwargs) @@ -676,6 +743,7 @@ def test_experience_details_with_a_non_educational_experience(self): 'admission/exports/recap/includes/curriculum_professional_experience.html', ) self.assertEqual(template_params['title'], _('Non-academic activity')) + self.assertEqual(template_params['curex_link_button'], '') self.assertEqual( template_params['edit_link_button'], '/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational/{experience_uuid}' @@ -705,44 +773,91 @@ def test_experience_details_with_a_non_educational_experience(self): self.assertEqual(template_params['CURRICULUM_ACTIVITY_LABEL'], CURRICULUM_ACTIVITY_LABEL) # Without the right to delete an experience - kwargs['can_delete_curriculum'] = False + perms['admission.delete_admission_curriculum'] = False template_params = experience_details_template(**kwargs) self.assertEqual(template_params['delete_link_button'], '') - kwargs['can_delete_curriculum'] = True + perms['admission.delete_admission_curriculum'] = True - # With a valuated experience + # With an EPC experience kwargs['experience'] = ExperienceNonAcademiqueDTOFactory(identifiant_externe='EPC-1') template_params = experience_details_template(**kwargs) + self.assertEqual(template_params['curex_link_button'], '') self.assertEqual( template_params['edit_link_button'], - '/osis_profile/{noma}/parcours_externe/edit/experience_non_academique/{experience_uuid}'.format( + '/osis_profile/{noma}/parcours_externe/edit/experience_non_academique/{experience_uuid}' + '?next=mypath&next_hash_url=parcours_anterieur__{experience_uuid}'.format( noma='0123456', experience_uuid=kwargs['experience'].uuid, ), ) + self.assertEqual( + template_params['duplicate_link_button'], + '/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational/{experience_uuid}' + '/duplicate?next=mypath&next_hash_url=parcours_anterieur__{experience_uuid}'.format( + proposition_uuid=proposition_uuid, + experience_uuid=kwargs['experience'].uuid, + ), + ) self.assertEqual(template_params['delete_link_button'], '') - # Without the right to update education - kwargs['can_update_curriculum'] = False + # Without the right to update the experience from the profile + perms['profil.can_edit_parcours_externe'] = False + template_params = experience_details_template(**kwargs) + + self.assertEqual(template_params['curex_link_button'], '') + self.assertEqual(template_params['edit_link_button'], '') + self.assertEqual( + template_params['duplicate_link_button'], + '/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational/{experience_uuid}' + '/duplicate?next=mypath&next_hash_url=parcours_anterieur__{experience_uuid}'.format( + proposition_uuid=proposition_uuid, + experience_uuid=kwargs['experience'].uuid, + ), + ) + self.assertEqual(template_params['delete_link_button'], '') + + # Without the right to update the experience + perms['admission.change_admission_curriculum'] = False template_params = experience_details_template(**kwargs) + self.assertEqual(template_params['curex_link_button'], '') self.assertEqual(template_params['edit_link_button'], '') self.assertEqual(template_params['duplicate_link_button'], '') self.assertEqual(template_params['delete_link_button'], '') def test_experience_details_with_secondary_studies(self): - proposition_uuid = uuid.uuid4() + general_admission = GeneralEducationAdmissionFactory() + proposition_uuid = general_admission.uuid experience = EtudesSecondairesDTOFactory() specific_questions = {Onglets.ETUDES_SECONDAIRES.name: [QuestionSpecifiqueDTOFactory()]} + + perms = { + 'admission.change_admission_secondary_studies': True, + 'profil.can_edit_parcours_externe': True, + 'profil.can_see_parcours_externe': True, + } + kwargs = { 'context': { - 'request': Mock(path='mypath'), - 'admission': MagicMock(noma_candidat='0123456'), + 'request': Mock( + path='mypath', + user=MagicMock( + _computed_permissions=perms, + ), + ), + 'view': MagicMock( + admission=general_admission, + proposition=MagicMock( + uuid=proposition_uuid, + noma_candidat='0123456', + formation=MagicMock(), + ), + ), }, 'resume_proposition': MagicMock( est_proposition_generale=True, @@ -755,10 +870,10 @@ def test_experience_details_with_secondary_studies(self): ), 'experience': experience, 'specific_questions': specific_questions, - 'can_update_education': True, } template_params = experience_details_template(**kwargs) self.assertEqual(template_params['custom_base_template'], 'admission/exports/recap/includes/education.html') + self.assertEqual(template_params['curex_link_button'], '') self.assertEqual( template_params['edit_link_button'], '/admissions/general-education/{proposition_uuid}/update/education' @@ -767,41 +882,68 @@ def test_experience_details_with_secondary_studies(self): experience_uuid=experience.uuid, ), ) + self.assertEqual(template_params['duplicate_link_button'], '') + self.assertEqual(template_params['delete_link_button'], '') self.assertEqual(template_params['specific_questions'], specific_questions[Onglets.ETUDES_SECONDAIRES.name]) - # With a valuated experience + # With an EPC experience kwargs['experience'] = EtudesSecondairesDTOFactory(identifiant_externe='EPC-1') template_params = experience_details_template(**kwargs) + self.assertEqual(template_params['curex_link_button'], '') self.assertEqual( template_params['edit_link_button'], - '/osis_profile/{noma}/parcours_externe/edit/etudes_secondaires'.format(noma='0123456'), + '/osis_profile/{noma}/parcours_externe/edit/etudes_secondaires' + '?next=mypath&next_hash_url=parcours_anterieur__{experience_uuid}'.format( + noma='0123456', + experience_uuid=kwargs['experience'].uuid, + ), ) + self.assertEqual(template_params['duplicate_link_button'], '') + self.assertEqual(template_params['delete_link_button'], '') # Without the right to update education - kwargs['can_update_education'] = False + perms['admission.change_admission_secondary_studies'] = False template_params = experience_details_template(**kwargs) + self.assertEqual(template_params['curex_link_button'], '') self.assertEqual(template_params['edit_link_button'], '') + self.assertEqual(template_params['duplicate_link_button'], '') + self.assertEqual(template_params['delete_link_button'], '') - @patch('admission.templatetags.admission.has_perm') - def test_checklist_experience_action_links_context_with_an_educational_experience(self, mock_has_perm): - mock_has_perm.return_value = True - - proposition_uuid = uuid.uuid4() + def test_checklist_experience_action_links_context_with_an_educational_experience(self): + general_admission = GeneralEducationAdmissionFactory() + proposition_uuid = general_admission.uuid experience = ExperienceAcademiqueDTOFactory( annees=[AnneeExperienceAcademiqueDTOFactory(uuid=uuid.uuid4(), annee=2020)], valorisee_par_admissions=[proposition_uuid], ) + perms = { + 'admission.change_admission_curriculum': True, + 'admission.change_admission_secondary_studies': True, + 'admission.delete_admission_curriculum': True, + 'profil.can_edit_parcours_externe': True, + 'profil.can_see_parcours_externe': True, + } + kwargs = { 'context': { - 'request': MagicMock(path='mypath'), - 'admission': MagicMock(noma_candidat='0123456'), - 'view': MagicMock(base_namespace='admission:general-education', kwargs={'uuid': proposition_uuid}), + 'request': Mock( + path='mypath', + user=MagicMock( + _computed_permissions=perms, + ), + ), + 'view': MagicMock( + base_namespace='admission:general-education', + kwargs={'uuid': proposition_uuid}, + admission=general_admission, + proposition=MagicMock(noma_candidat='0123456'), + ), }, 'prefix': 'prefix', 'experience': experience, @@ -816,25 +958,28 @@ def test_checklist_experience_action_links_context_with_an_educational_experienc self.assertEqual(context['prefix'], 'prefix') self.assertEqual( context['update_url'], - f'/admissions/general-education/{proposition_uuid}/update/curriculum/educational/{experience.uuid}{next_url_suffix}', + f'/admissions/general-education/{proposition_uuid}/update/curriculum/educational' + f'/{experience.uuid}{next_url_suffix}', ) self.assertEqual( context['delete_url'], - f'/admissions/general-education/{proposition_uuid}/update/curriculum/educational/{experience.uuid}/delete{next_url_suffix}', + f'/admissions/general-education/{proposition_uuid}/update/curriculum/educational' + f'/{experience.uuid}/delete{next_url_suffix}', ) self.assertEqual( context['duplicate_url'], - f'/admissions/general-education/{proposition_uuid}/update/curriculum/educational/{experience.uuid}/duplicate', + f'/admissions/general-education/{proposition_uuid}/update/curriculum/educational' + f'/{experience.uuid}/duplicate', ) self.assertEqual(context['experience_uuid'], str(experience.uuid)) self.assertEqual(context['edit_link_button_in_new_tab'], False) - mock_has_perm.return_value = False + perms['admission.delete_admission_curriculum'] = False context = checklist_experience_action_links_context(**kwargs) self.assertEqual(context['delete_url'], '') - mock_has_perm.return_value = True + perms['admission.delete_admission_curriculum'] = False # With a valuated experience experience = ExperienceAcademiqueDTOFactory( @@ -853,22 +998,37 @@ def test_checklist_experience_action_links_context_with_an_educational_experienc ) self.assertEqual(context['delete_url'], '') - @patch('admission.templatetags.admission.has_perm') - def test_checklist_experience_action_links_context_with_a_non_educational_experience(self, mock_has_perm): - mock_has_perm.return_value = True - - proposition_uuid = uuid.uuid4() + def test_checklist_experience_action_links_context_with_a_non_educational_experience(self): + general_admission = GeneralEducationAdmissionFactory() + proposition_uuid = general_admission.uuid experience = ExperienceNonAcademiqueDTOFactory( valorisee_par_admissions=[proposition_uuid], date_fin=datetime.date(2020, 12, 31), ) + perms = { + 'admission.change_admission_curriculum': True, + 'admission.change_admission_secondary_studies': True, + 'admission.delete_admission_curriculum': True, + 'profil.can_edit_parcours_externe': True, + 'profil.can_see_parcours_externe': True, + } + kwargs = { 'context': { - 'request': MagicMock(path='mypath'), - 'admission': MagicMock(noma_candidat='0123456'), - 'view': MagicMock(base_namespace='admission:general-education', kwargs={'uuid': proposition_uuid}), + 'request': Mock( + path='mypath', + user=MagicMock( + _computed_permissions=perms, + ), + ), + 'view': MagicMock( + base_namespace='admission:general-education', + kwargs={'uuid': proposition_uuid}, + admission=general_admission, + proposition=MagicMock(noma_candidat='0123456'), + ), }, 'prefix': 'prefix', 'experience': experience, @@ -883,25 +1043,28 @@ def test_checklist_experience_action_links_context_with_a_non_educational_experi self.assertEqual(context['prefix'], 'prefix') self.assertEqual( context['update_url'], - f'/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational/{experience.uuid}{next_url_suffix}', + f'/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational' + f'/{experience.uuid}{next_url_suffix}', ) self.assertEqual( context['delete_url'], - f'/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational/{experience.uuid}/delete{next_url_suffix}', + f'/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational' + f'/{experience.uuid}/delete{next_url_suffix}', ) self.assertEqual( context['duplicate_url'], - f'/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational/{experience.uuid}/duplicate', + f'/admissions/general-education/{proposition_uuid}/update/curriculum/non_educational' + f'/{experience.uuid}/duplicate', ) self.assertEqual(context['experience_uuid'], str(experience.uuid)) self.assertEqual(context['edit_link_button_in_new_tab'], False) - mock_has_perm.return_value = False + perms['admission.delete_admission_curriculum'] = False context = checklist_experience_action_links_context(**kwargs) self.assertEqual(context['delete_url'], '') - mock_has_perm.return_value = True + perms['admission.delete_admission_curriculum'] = True # With a valuated experience experience = ExperienceNonAcademiqueDTOFactory( @@ -916,20 +1079,38 @@ def test_checklist_experience_action_links_context_with_a_non_educational_experi self.assertEqual(context['edit_link_button_in_new_tab'], True) self.assertEqual( context['update_url'], - f'/osis_profile/0123456/parcours_externe/edit/experience_non_academique/{experience.uuid}', + f'/osis_profile/0123456/parcours_externe/edit/experience_non_academique/{experience.uuid}{next_url_suffix}', ) self.assertEqual(context['delete_url'], '') def test_checklist_experience_action_links_context_with_secondary_studies(self): - proposition_uuid = uuid.uuid4() + general_admission = GeneralEducationAdmissionFactory() + proposition_uuid = general_admission.uuid experience = EtudesSecondairesDTOFactory() + perms = { + 'admission.change_admission_curriculum': True, + 'admission.change_admission_secondary_studies': True, + 'admission.delete_admission_curriculum': True, + 'profil.can_edit_parcours_externe': True, + 'profil.can_see_parcours_externe': True, + } + kwargs = { 'context': { - 'request': MagicMock(path='mypath'), - 'admission': MagicMock(noma_candidat='0123456'), - 'view': MagicMock(base_namespace='admission:general-education', kwargs={'uuid': proposition_uuid}), + 'request': Mock( + path='mypath', + user=MagicMock( + _computed_permissions=perms, + ), + ), + 'view': MagicMock( + base_namespace='admission:general-education', + kwargs={'uuid': proposition_uuid}, + admission=general_admission, + proposition=MagicMock(noma_candidat='0123456'), + ), }, 'prefix': 'prefix', 'experience': experience, @@ -958,19 +1139,37 @@ def test_checklist_experience_action_links_context_with_secondary_studies(self): self.assertEqual(context['edit_link_button_in_new_tab'], True) self.assertEqual( context['update_url'], - f'/osis_profile/0123456/parcours_externe/edit/etudes_secondaires', + f'/osis_profile/0123456/parcours_externe/edit/etudes_secondaires{next_url_suffix}', ) def test_checklist_experience_action_links_context_with_an_internal_experience(self): - proposition_uuid = uuid.uuid4() + general_admission = GeneralEducationAdmissionFactory() + proposition_uuid = general_admission.uuid experience = ExperienceParcoursInterneDTOFactory(annees=[]) + perms = { + 'admission.change_admission_curriculum': True, + 'admission.change_admission_secondary_studies': True, + 'admission.delete_admission_curriculum': True, + 'profil.can_edit_parcours_externe': True, + 'profil.can_see_parcours_externe': True, + } + kwargs = { 'context': { - 'request': MagicMock(path='mypath'), - 'admission': MagicMock(noma_candidat='0123456'), - 'view': MagicMock(base_namespace='admission:general-education', kwargs={'uuid': proposition_uuid}), + 'request': Mock( + path='mypath', + user=MagicMock( + _computed_permissions=perms, + ), + ), + 'view': MagicMock( + base_namespace='admission:general-education', + kwargs={'uuid': proposition_uuid}, + admission=general_admission, + proposition=MagicMock(noma_candidat='0123456'), + ), }, 'prefix': 'prefix', 'experience': experience, diff --git a/tests/utils/test_experience_urls.py b/tests/utils/test_experience_urls.py index 5085b8f85..620c80198 100644 --- a/tests/utils/test_experience_urls.py +++ b/tests/utils/test_experience_urls.py @@ -186,14 +186,7 @@ def test_get_urls_of_an_epc_academic_experience_if_the_user_can_change_the_cv(se ), ) self.assertEqual(experience_urls['edit_new_link_tab'], True) - self.assertEqual( - experience_urls['duplicate_url'], - '/admissions/continuing-education/{admission_uuid}/update/curriculum/educational/' - '{experience_uuid}/duplicate'.format( - admission_uuid=self.continuing_education.uuid, - experience_uuid=academic_experience.uuid, - ), - ) + self.assertEqual(experience_urls['duplicate_url'], '') def test_get_urls_of_an_epc_academic_experience_if_the_user_cannot_change_the_profile(self): academic_experience = ExperienceAcademiqueDTOFactory( @@ -218,14 +211,7 @@ def test_get_urls_of_an_epc_academic_experience_if_the_user_cannot_change_the_pr self.assertEqual(experience_urls['delete_url'], '') self.assertEqual(experience_urls['edit_url'], '') self.assertEqual(experience_urls['edit_new_link_tab'], False) - self.assertEqual( - experience_urls['duplicate_url'], - '/admissions/continuing-education/{admission_uuid}/update/curriculum/educational/' - '{experience_uuid}/duplicate'.format( - admission_uuid=self.continuing_education.uuid, - experience_uuid=academic_experience.uuid, - ), - ) + self.assertEqual(experience_urls['duplicate_url'], '') def test_get_urls_of_a_non_academic_experience_if_the_user_cannot_change_the_cv(self): non_academic_experience = ExperienceNonAcademiqueDTOFactory() diff --git a/tests/views/common/form_tabs/curriculum/test_educational_experience_delete.py b/tests/views/common/form_tabs/curriculum/test_educational_experience_delete.py index 4f9e24693..437f0979f 100644 --- a/tests/views/common/form_tabs/curriculum/test_educational_experience_delete.py +++ b/tests/views/common/form_tabs/curriculum/test_educational_experience_delete.py @@ -371,6 +371,5 @@ def test_delete_experience_from_doctorate_curriculum_is_allowed_for_sic_users(se self.assertRedirects( response=response, fetch_redirect_response=False, - expected_url=resolve_url('admission:doctorate:curriculum', uuid=self.doctorate_admission.uuid), + expected_url=resolve_url('admission:doctorate:checklist', uuid=self.doctorate_admission.uuid), ) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) diff --git a/tests/views/common/form_tabs/curriculum/test_educational_experience_duplicate.py b/tests/views/common/form_tabs/curriculum/test_educational_experience_duplicate.py index b0e80675f..97bc76c5b 100644 --- a/tests/views/common/form_tabs/curriculum/test_educational_experience_duplicate.py +++ b/tests/views/common/form_tabs/curriculum/test_educational_experience_duplicate.py @@ -535,5 +535,5 @@ def test_duplicate_experience_from_doctorate_curriculum_is_allowed_for_sic_users self.assertRedirects( response=response, fetch_redirect_response=False, - expected_url=resolve_url('admission:doctorate:curriculum', uuid=self.doctorate_admission.uuid), + expected_url=resolve_url('admission:doctorate:checklist', uuid=self.doctorate_admission.uuid), ) diff --git a/tests/views/common/form_tabs/curriculum/test_non_educational_experience_delete.py b/tests/views/common/form_tabs/curriculum/test_non_educational_experience_delete.py index eeeafc208..4c1b0155f 100644 --- a/tests/views/common/form_tabs/curriculum/test_non_educational_experience_delete.py +++ b/tests/views/common/form_tabs/curriculum/test_non_educational_experience_delete.py @@ -280,11 +280,15 @@ def test_delete_experience_from_doctorate_curriculum_is_not_allowed_for_fac_user def test_delete_experience_from_doctorate_curriculum_is_allowed_for_sic_users(self): self.client.force_login(self.sic_manager_user) - response = self.client.delete(self.doctorate_delete_url) + + admission_url = resolve_url('admission') + expected_url = f'{admission_url}#custom_hash' + + response = self.client.delete(f'{self.doctorate_delete_url}?next={admission_url}&next_hash_url=custom_hash') self.assertRedirects( response=response, fetch_redirect_response=False, - expected_url=resolve_url('admission:doctorate:curriculum', uuid=self.doctorate_admission.uuid), + expected_url=expected_url, ) self.assertEqual(response.status_code, status.HTTP_302_FOUND) diff --git a/tests/views/common/form_tabs/curriculum/test_non_educational_experience_duplicate.py b/tests/views/common/form_tabs/curriculum/test_non_educational_experience_duplicate.py index 71b1df27e..4e9d488ce 100644 --- a/tests/views/common/form_tabs/curriculum/test_non_educational_experience_duplicate.py +++ b/tests/views/common/form_tabs/curriculum/test_non_educational_experience_duplicate.py @@ -366,10 +366,13 @@ def test_duplicate_experience_from_doctorate_curriculum_is_allowed_for_fac_users def test_duplicate_experience_from_doctorate_curriculum_is_allowed_for_sic_users(self): self.client.force_login(self.sic_manager_user) - response = self.client.post(self.doctorate_duplicate_url) + + admission_url = resolve_url('admission') + expected_url = f'{admission_url}#custom_hash' + + response = self.client.post(f'{self.duplicate_url}?next={admission_url}&next_hash_url=custom_hash') self.assertRedirects( response=response, fetch_redirect_response=False, - expected_url=resolve_url('admission:doctorate:curriculum', uuid=self.doctorate_admission.uuid), + expected_url=expected_url, ) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) diff --git a/utils.py b/utils.py index f71bdebd4..d773112ed 100644 --- a/utils.py +++ b/utils.py @@ -24,12 +24,11 @@ # # ############################################################################## import itertools -import json import os import uuid from collections import defaultdict from contextlib import suppress -from typing import Dict, Union, Iterable, List, Optional +from typing import Dict, Union, Iterable, List import weasyprint from django.conf import settings @@ -61,7 +60,6 @@ from admission.ddd.parcours_doctoral.domain.model.enums import ChoixStatutDoctorat from admission.infrastructure.admission.domain.service.annee_inscription_formation import ( ADMISSION_CONTEXT_BY_OSIS_EDUCATION_TYPE, - AnneeInscriptionFormationTranslator, ) from admission.mail_templates import ( ADMISSION_EMAIL_CONFIRMATION_PAPER_INFO_STUDENT, @@ -525,10 +523,30 @@ def get_experience_urls( 'delete_url': '', 'duplicate_url': '', 'details_url': '', + 'curex_url': '', 'edit_new_link_tab': False, } - can_update_curriculum_via_admission = user.has_perm(perm='admission.change_admission_curriculum', obj=admission) + if not getattr(user, '_computed_permissions', None): + computed_permissions = { + 'admission.change_admission_curriculum': user.has_perm( + perm='admission.change_admission_curriculum', + obj=admission, + ), + 'admission.change_admission_secondary_studies': user.has_perm( + perm='admission.change_admission_secondary_studies', + obj=admission, + ), + 'admission.delete_admission_curriculum': user.has_perm( + perm='admission.delete_admission_curriculum', + obj=admission, + ), + 'profil.can_edit_parcours_externe': user.has_perm(perm='profil.can_edit_parcours_externe'), + 'profil.can_see_parcours_externe': user.has_perm(perm='profil.can_see_parcours_externe'), + } + setattr(user, '_computed_permissions', computed_permissions) + else: + computed_permissions = getattr(user, '_computed_permissions') if isinstance(experience, ExperienceAcademiqueDTO): res_context['details_url'] = resolve_url( @@ -537,38 +555,38 @@ def get_experience_urls( experience_uuid=experience.uuid, ) - if not can_update_curriculum_via_admission: + if not computed_permissions['admission.change_admission_curriculum']: return res_context - res_context['duplicate_url'] = resolve_url( - f'{base_namespace}:update:curriculum:educational_duplicate', - uuid=admission.uuid, - experience_uuid=experience.uuid, - ) - if experience.epc_experience: - can_update_curriculum_via_profile = user.has_perm(perm='profil.can_edit_parcours_externe') - - if can_update_curriculum_via_profile and candidate_noma: - res_context['edit_url'] = resolve_url( - 'edit-experience-academique-view', - noma=candidate_noma, - experience_uuid=experience.annees[0].uuid, - ) - res_context['edit_new_link_tab'] = True + if candidate_noma: + if computed_permissions['profil.can_see_parcours_externe']: + res_context['curex_url'] = resolve_url( + 'parcours-externe-view', + noma=candidate_noma, + ) + if computed_permissions['profil.can_edit_parcours_externe']: + res_context['edit_url'] = resolve_url( + 'edit-experience-academique-view', + noma=candidate_noma, + experience_uuid=experience.annees[0].uuid, + ) + res_context['edit_new_link_tab'] = True else: + res_context['duplicate_url'] = resolve_url( + f'{base_namespace}:update:curriculum:educational_duplicate', + uuid=admission.uuid, + experience_uuid=experience.uuid, + ) + res_context['edit_url'] = resolve_url( f'{base_namespace}:update:curriculum:educational', uuid=admission.uuid, experience_uuid=experience.uuid, ) - can_delete_curriculum_via_admission = user.has_perm( - perm='admission.delete_admission_curriculum', - obj=admission, - ) - if can_delete_curriculum_via_admission: + if computed_permissions['admission.delete_admission_curriculum']: res_context['delete_url'] = resolve_url( f'{base_namespace}:update:curriculum:educational_delete', uuid=admission.uuid, @@ -582,7 +600,7 @@ def get_experience_urls( experience_uuid=experience.uuid, ) - if not can_update_curriculum_via_admission: + if not computed_permissions['admission.change_admission_curriculum']: return res_context res_context['duplicate_url'] = resolve_url( @@ -592,15 +610,14 @@ def get_experience_urls( ) if experience.epc_experience: - can_update_curriculum_via_profile = user.has_perm(perm='profil.can_edit_parcours_externe') - - if can_update_curriculum_via_profile and candidate_noma: - res_context['edit_url'] = resolve_url( - 'edit-experience-non-academique-view', - noma=candidate_noma, - experience_uuid=experience.uuid, - ) - res_context['edit_new_link_tab'] = True + if candidate_noma: + if computed_permissions['profil.can_edit_parcours_externe']: + res_context['edit_url'] = resolve_url( + 'edit-experience-non-academique-view', + noma=candidate_noma, + experience_uuid=experience.uuid, + ) + res_context['edit_new_link_tab'] = True else: res_context['edit_url'] = resolve_url( @@ -609,11 +626,7 @@ def get_experience_urls( experience_uuid=experience.uuid, ) - can_delete_curriculum_via_admission = user.has_perm( - perm='admission.delete_admission_curriculum', - obj=admission, - ) - if can_delete_curriculum_via_admission: + if computed_permissions['admission.delete_admission_curriculum']: res_context['delete_url'] = resolve_url( f'{base_namespace}:update:curriculum:non_educational_delete', uuid=admission.uuid, @@ -626,18 +639,17 @@ def get_experience_urls( uuid=admission.uuid, ) - if not can_update_curriculum_via_admission: + if not computed_permissions['admission.change_admission_secondary_studies']: return res_context if experience.epc_experience: - can_update_curriculum_via_profile = user.has_perm(perm='profil.can_edit_parcours_externe') - - if can_update_curriculum_via_profile and candidate_noma: - res_context['edit_url'] = resolve_url( - 'edit-etudes-secondaires-view', - noma=candidate_noma, - ) - res_context['edit_new_link_tab'] = True + if candidate_noma: + if computed_permissions['profil.can_edit_parcours_externe']: + res_context['edit_url'] = resolve_url( + 'edit-etudes-secondaires-view', + noma=candidate_noma, + ) + res_context['edit_new_link_tab'] = True else: res_context['edit_url'] = resolve_url( diff --git a/views/common/form_tabs/curriculum.py b/views/common/form_tabs/curriculum.py index a3a90123d..34c692a55 100644 --- a/views/common/form_tabs/curriculum.py +++ b/views/common/form_tabs/curriculum.py @@ -143,7 +143,7 @@ def get_success_url(self): if self.next_url: return self.next_url - if self.is_general: + if self.is_general or self.is_doctorate: return resolve_url( f'{self.base_namespace}:update:curriculum:educational', uuid=self.admission_uuid, @@ -153,7 +153,10 @@ def get_success_url(self): return resolve_url(f'{self.base_namespace}:curriculum', uuid=self.admission_uuid) def delete_url(self): - if self.experience_id: + if self.experience_id and self.request.user.has_perm( + perm='admission.delete_admission_curriculum', + obj=self.admission, + ): return resolve_url( f'{self.base_namespace}:update:curriculum:educational_delete', uuid=self.admission_uuid, @@ -163,7 +166,7 @@ def delete_url(self): def get_context_data(self, **kwargs): context_data = super().get_context_data(**kwargs) - if self.is_continuing or self.is_doctorate: + if self.is_continuing: context_data['next_url'] = self.get_success_url() context_data['prevent_quitting_template'] = 'admission/includes/back_to_cv_overview_link.html' else: @@ -240,7 +243,7 @@ def get_success_url(self): if self.next_url: return self.next_url - if self.is_general: + if self.is_general or self.is_doctorate: return resolve_url( f'{self.base_namespace}:update:curriculum:non_educational', uuid=self.admission_uuid, @@ -250,7 +253,10 @@ def get_success_url(self): return resolve_url(f'{self.base_namespace}:curriculum', uuid=self.admission_uuid) def delete_url(self): - if self.experience_id: + if self.experience_id and self.request.user.has_perm( + perm='admission.delete_admission_curriculum', + obj=self.admission, + ): return resolve_url( f'{self.base_namespace}:update:curriculum:non_educational_delete', uuid=self.admission_uuid, @@ -260,7 +266,7 @@ def delete_url(self): def get_context_data(self, **kwargs): context_data = super().get_context_data(**kwargs) - if self.is_continuing or self.is_doctorate: + if self.is_continuing: context_data['next_url'] = self.get_success_url() context_data['prevent_quitting_template'] = 'admission/includes/back_to_cv_overview_link.html' else: @@ -353,7 +359,7 @@ def get_success_url(self): } return ( self.next_url or reverse(f'{self.base_namespace}:checklist', kwargs=kwargs) - if self.is_general + if self.is_general or self.is_doctorate else reverse(f'{self.base_namespace}:curriculum', kwargs=kwargs) ) @@ -506,7 +512,7 @@ def get_success_url(self): } return ( self.next_url or reverse(f'{self.base_namespace}:checklist', kwargs=kwargs) - if self.is_general + if self.is_general or self.is_doctorate else reverse(f'{self.base_namespace}:curriculum', kwargs=kwargs) ) diff --git a/views/doctorate/details/checklist/base.py b/views/doctorate/details/checklist/base.py index 28af3b2bf..3e6a7392c 100644 --- a/views/doctorate/details/checklist/base.py +++ b/views/doctorate/details/checklist/base.py @@ -160,8 +160,6 @@ def checklist_documents_by_tab(cls, specific_questions: List[QuestionSpecifiqueD for document in DocumentsAssimilation: assimilation_documents.add(document) - secondary_studies_attachments = set(DocumentsEtudesSecondaires.keys()) - documents_by_tab = { OngletsChecklist.assimilation.name: assimilation_documents, OngletsChecklist.financabilite.name: { @@ -177,16 +175,12 @@ def checklist_documents_by_tab(cls, specific_questions: List[QuestionSpecifiqueD 'DIPLOME_EQUIVALENCE', 'CURRICULUM', 'ADDITIONAL_DOCUMENTS', - *secondary_studies_attachments, }, OngletsChecklist.donnees_personnelles.name: assimilation_documents, OngletsChecklist.decision_facultaire.name: { 'ATTESTATION_ACCORD_FACULTAIRE', 'ATTESTATION_REFUS_FACULTAIRE', }, - f'{OngletsChecklist.parcours_anterieur.name}__{OngletsDemande.ETUDES_SECONDAIRES.name}': ( - secondary_studies_attachments - ), OngletsChecklist.decision_sic.name: { 'ATTESTATION_ACCORD_SIC', 'ATTESTATION_ACCORD_ANNEXE_SIC', @@ -200,9 +194,6 @@ def checklist_documents_by_tab(cls, specific_questions: List[QuestionSpecifiqueD # Add documents from the specific questions checklist_target_tab_by_specific_question_tab = { Onglets.CURRICULUM.name: OngletsChecklist.parcours_anterieur.name, - Onglets.ETUDES_SECONDAIRES.name: ( - f'{OngletsChecklist.parcours_anterieur.name}__{OngletsDemande.ETUDES_SECONDAIRES.name}' - ), } for specific_question in specific_questions: @@ -377,6 +368,7 @@ def get_context_data(self, **kwargs): if experience_id: context['all_experience_authentication_history_entries'].setdefault(experience_id, entry) + # Past experiences children_by_identifier = { child['extra']['identifiant']: child for child in children if child.get('extra', {}).get('identifiant') } @@ -592,7 +584,6 @@ def _get_experiences_by_uuid(self, resume: ResumeCandidatDTO): experiences[str(experience_academique.uuid)] = experience_academique for experience_non_academique in resume.curriculum.experiences_non_academiques: experiences[str(experience_non_academique.uuid)] = experience_non_academique - experiences[OngletsDemande.ETUDES_SECONDAIRES.name] = resume.etudes_secondaires return experiences