diff --git a/castellum/recruitment/templates/recruitment/contact.html b/castellum/recruitment/templates/recruitment/contact.html index 398e66f1221586a9b88465dc2f88b16aa0c95c40..fc06518f69e22859aa89ccbf5236503db6d08abf 100644 --- a/castellum/recruitment/templates/recruitment/contact.html +++ b/castellum/recruitment/templates/recruitment/contact.html @@ -72,16 +72,19 @@ {% if can_change_contact %} {% trans 'Edit contact data'%} {% endif %} - {% has_perm 'subjects.change_subject' user study as can_change_subject %} - {% if can_change_subject %} - - {% trans 'Edit subject' %} - - {% endif %} {% has_perm 'recruitment.change_attributeset' user study as can_change_attributeset %} {% if can_change_attributeset %} {% trans 'Edit attributes'%} {% endif %} + {% has_perm 'subjects.change_subject' user study as can_change_subject %} + {% if can_change_subject %} + + {% trans 'Edit data protection' %} + + + {% trans 'Edit additional info' %} + + {% endif %}
diff --git a/castellum/recruitment/urls.py b/castellum/recruitment/urls.py index a32baf4b92b38c3129379237bbd2393c5f860405..1e4b3991e595946591fa146d6218d60b9702e003 100644 --- a/castellum/recruitment/urls.py +++ b/castellum/recruitment/urls.py @@ -23,16 +23,17 @@ from django.urls import path from .feeds import FollowUpFeedForStudy from .feeds import FollowUpFeedForUser +from .views import AdditionalInfoUpdateView from .views import AttributeSetUpdateView from .views import ContactUpdateView from .views import ContactView +from .views import DataProtectionUpdateView from .views import MailRecruitmentView from .views import RecruitmentViewInvited from .views import RecruitmentViewOpen from .views import RecruitmentViewUnsuitable from .views import SearchView from .views import StudyListView -from .views import SubjectUpdateView app_name = 'recruitment' urlpatterns = [ @@ -60,8 +61,13 @@ urlpatterns = [ name='attributeset-update', ), path( - '//update-subject/', - SubjectUpdateView.as_view(), - name='subject-update', + '//update-data-protection/', + DataProtectionUpdateView.as_view(), + name='data-protection-update', + ), + path( + '//update-additional-info/', + AdditionalInfoUpdateView.as_view(), + name='additional-info-update', ), ] diff --git a/castellum/recruitment/views.py b/castellum/recruitment/views.py index b1700e79587ce074192657ce563a0bd175d16b14..62628a1610592a2ffff74bccd2e724bdecb0ea38 100644 --- a/castellum/recruitment/views.py +++ b/castellum/recruitment/views.py @@ -51,7 +51,8 @@ from castellum.recruitment.mixins import BaseAttributeSetUpdateView from castellum.recruitment.models.attributesets import get_description_by_statistics_rank from castellum.studies.mixins import StudyMixin from castellum.studies.models import Study -from castellum.subjects.mixins import BaseSubjectUpdateView +from castellum.subjects.mixins import BaseAdditionalInfoUpdateView +from castellum.subjects.mixins import BaseDataProtectionUpdateView from castellum.subjects.mixins import SubjectMixin from castellum.utils.views import GetFormView @@ -468,16 +469,14 @@ class ContactView(StudyMixin, SubjectMixin, PermissionRequiredMixin, UpdateView) return reverse('recruitment:recruitment-open', args=[self.object.study.pk]) -class ContactUpdateView(StudyMixin, BaseContactUpdateView): +class RecruitmentUpdateMixin(StudyMixin): study_status = [Study.EXECUTION] def get_object(self): - participation_request = get_object_or_404( + return get_object_or_404( ParticipationRequest, study=self.study, pk=self.kwargs['pk'] ) - return participation_request.subject.contact - def get_success_url(self): return reverse('recruitment:contact', args=[self.kwargs['study_pk'], self.kwargs['pk']]) @@ -490,41 +489,28 @@ class ContactUpdateView(StudyMixin, BaseContactUpdateView): return context -class AttributeSetUpdateView(StudyMixin, BaseAttributeSetUpdateView): - study_status = [Study.EXECUTION] - +class ContactUpdateView(RecruitmentUpdateMixin, BaseContactUpdateView): def get_object(self): - participation_request = get_object_or_404( - ParticipationRequest, study=self.study, pk=self.kwargs['pk'] - ) - return participation_request.subject.attributeset + participation_request = super().get_object() + return participation_request.subject.contact - def get_success_url(self): - return reverse('recruitment:contact', args=[self.kwargs['study_pk'], self.kwargs['pk']]) - def get_back_url(self): - return self.get_success_url() +class AttributeSetUpdateView(RecruitmentUpdateMixin, BaseAttributeSetUpdateView): + def get_object(self): + participation_request = super().get_object() + return participation_request.subject.attributeset -class SubjectUpdateView(StudyMixin, BaseSubjectUpdateView): - study_status = [Study.EXECUTION] - +class DataProtectionUpdateView(RecruitmentUpdateMixin, BaseDataProtectionUpdateView): def get_object(self): - participation_request = get_object_or_404( - ParticipationRequest, study=self.study, pk=self.kwargs['pk'] - ) + participation_request = super().get_object() return participation_request.subject - def get_success_url(self): - return reverse('recruitment:contact', args=[self.kwargs['study_pk'], self.kwargs['pk']]) - - def get_back_url(self): - return self.get_success_url() - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['base_template'] = "recruitment/base.html" - return context +class AdditionalInfoUpdateView(RecruitmentUpdateMixin, BaseAdditionalInfoUpdateView): + def get_object(self): + participation_request = super().get_object() + return participation_request.subject class SearchView(LoginRequiredMixin, GetFormView): diff --git a/castellum/subjects/forms.py b/castellum/subjects/forms.py index 9347c3d29634963fc1f431ae88f3019e94ef1b8b..a0116f515469636fb26ba217ba1a0ab648c93c83 100644 --- a/castellum/subjects/forms.py +++ b/castellum/subjects/forms.py @@ -32,11 +32,11 @@ from .models import ConsentDocument from .models import Subject -class SubjectForm(forms.ModelForm): +class DataProtectionForm(forms.ModelForm): class Meta: model = Subject - exclude = ('to_be_deleted', 'to_be_deleted_notified', 'export_requested') + fields = ('privacy_level', 'no_recruitment') widgets = { 'privacy_level': forms.RadioSelect, 'source': DatalistWidget(datalist=( diff --git a/castellum/subjects/mixins.py b/castellum/subjects/mixins.py index 275a07e19926be9e17d2e8aec472d75fae99768d..c2548417392e9c40686a5740084d648bdb1fa9f3 100644 --- a/castellum/subjects/mixins.py +++ b/castellum/subjects/mixins.py @@ -29,7 +29,7 @@ from django.views.generic import UpdateView from castellum.castellum_auth.mixins import PermissionRequiredMixin -from .forms import SubjectForm +from .forms import DataProtectionForm from .models import Subject from .models import SubjectNote @@ -61,16 +61,70 @@ class SubjectMixin: return context -class BaseSubjectUpdateView(SubjectMixin, PermissionRequiredMixin, UpdateView): +class BaseDataProtectionUpdateView(SubjectMixin, PermissionRequiredMixin, UpdateView): model = Subject - form_class = SubjectForm + form_class = DataProtectionForm permission_required = 'subjects.change_subject' + template_name = 'subjects/subject_data_protection_form.html' def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs['user'] = self.request.user return kwargs + def form_valid(self, form): + if settings.CASTELLUM_DELETE_NOTIFICATION_TO: + old = Subject.objects.get(pk=self.object.pk) + if self.object.export_requested and not old.export_requested: + rel = reverse('subjects:detail', args=[self.object.pk]) + url = self.request.build_absolute_uri(rel) + + self.object.to_be_deleted_notified = send_mail( + settings.CASTELLUM_EXPORT_SUBJECT_NOTIFICATION_SUBJECT, + settings.CASTELLUM_EXPORT_SUBJECT_NOTIFICATION_BODY.format(url=url), + settings.DEFAULT_FROM_EMAIL, + [settings.CASTELLUM_DELETE_NOTIFICATION_TO], + ) + + if self.object.to_be_deleted and not self.object.to_be_deleted_notified: + rel = reverse('subjects:detail', args=[self.object.pk]) + url = self.request.build_absolute_uri(rel) + + self.object.to_be_deleted_notified = send_mail( + settings.CASTELLUM_DELETE_SUBJECT_NOTIFICATION_SUBJECT, + settings.CASTELLUM_DELETE_SUBJECT_NOTIFICATION_BODY.format(url=url), + settings.DEFAULT_FROM_EMAIL, + [settings.CASTELLUM_DELETE_NOTIFICATION_TO], + ) + + # If a user explicitly removes the ``to_be_deleted`` they + # expect that this task is done. If there are still reasons + # for deletion there should be a new notificaition. + if not self.object.to_be_deleted and self.object.to_be_deleted_notified: + old = Subject.objects.get(pk=self.object.pk) + if old.to_be_deleted: + self.object.to_be_deleted_notified = False + + return super().form_valid(form) + + +class BaseAdditionalInfoUpdateView(SubjectMixin, PermissionRequiredMixin, UpdateView): + model = Subject + fields = ( + 'note_hard_of_hearing', + 'note_difficult_to_understand', + 'note_abusive_language', + 'availability_monday', + 'availability_tuesday', + 'availability_wednesday', + 'availability_thursday', + 'availability_friday', + 'not_available_until', + 'source', + ) + permission_required = 'subjects.change_subject' + template_name = 'subjects/subject_additional_info_form.html' + def get_notes_form(self): form_class = forms.modelform_factory(SubjectNote, fields=('content',)) return form_class(prefix='{prefix}') @@ -80,7 +134,6 @@ class BaseSubjectUpdateView(SubjectMixin, PermissionRequiredMixin, UpdateView): SubjectNote, fields=('content',), extra=0, can_delete=True ) kwargs = self.get_form_kwargs() - kwargs.pop('user') kwargs.pop('instance') kwargs.pop('initial') return formset_class(queryset=SubjectNote.objects.filter(subject=self.object), **kwargs) @@ -108,38 +161,6 @@ class BaseSubjectUpdateView(SubjectMixin, PermissionRequiredMixin, UpdateView): ) def form_valid(self, form, notes_formset): - if settings.CASTELLUM_DELETE_NOTIFICATION_TO: - old = Subject.objects.get(pk=self.object.pk) - if self.object.export_requested and not old.export_requested: - rel = reverse('subjects:detail', args=[self.object.pk]) - url = self.request.build_absolute_uri(rel) - - self.object.to_be_deleted_notified = send_mail( - settings.CASTELLUM_EXPORT_SUBJECT_NOTIFICATION_SUBJECT, - settings.CASTELLUM_EXPORT_SUBJECT_NOTIFICATION_BODY.format(url=url), - settings.DEFAULT_FROM_EMAIL, - [settings.CASTELLUM_DELETE_NOTIFICATION_TO], - ) - - if self.object.to_be_deleted and not self.object.to_be_deleted_notified: - rel = reverse('subjects:detail', args=[self.object.pk]) - url = self.request.build_absolute_uri(rel) - - self.object.to_be_deleted_notified = send_mail( - settings.CASTELLUM_DELETE_SUBJECT_NOTIFICATION_SUBJECT, - settings.CASTELLUM_DELETE_SUBJECT_NOTIFICATION_BODY.format(url=url), - settings.DEFAULT_FROM_EMAIL, - [settings.CASTELLUM_DELETE_NOTIFICATION_TO], - ) - - # If a user explicitly removes the ``to_be_deleted`` they - # expect that this task is done. If there are still reasons - # for deletion there should be a new notificaition. - if not self.object.to_be_deleted and self.object.to_be_deleted_notified: - old = Subject.objects.get(pk=self.object.pk) - if old.to_be_deleted: - self.object.to_be_deleted_notified = False - response = super().form_valid(form) for subform in notes_formset: diff --git a/castellum/subjects/templates/subjects/subject_additional_info_form.html b/castellum/subjects/templates/subjects/subject_additional_info_form.html new file mode 100644 index 0000000000000000000000000000000000000000..ac1153a3bde1c75a7e9b203e5247228c0133fb86 --- /dev/null +++ b/castellum/subjects/templates/subjects/subject_additional_info_form.html @@ -0,0 +1,96 @@ +{% extends base_template|default:"subjects/base.html" %} +{% load static i18n bootstrap4 subjects utils %} + +{% block title %} + {% trans "Edit subject" %} · {{ block.super }} +{% endblock %} + +{% block content %} + + +
+ {% for error in form.non_field_errors %} + + {% endfor %} + + {% csrf_token %} + +
+ {% trans "Availability" %} + +
+
+ {% bootstrap_field form.availability_monday %} +
+
+ {% bootstrap_field form.availability_tuesday %} +
+
+ {% bootstrap_field form.availability_wednesday %} +
+
+ {% bootstrap_field form.availability_thursday %} +
+
+ {% bootstrap_field form.availability_friday %} +
+
+
+ + {% bootstrap_field form.not_available_until %} + +
+ {% trans "Notes" %} + + {% bootstrap_field form.note_hard_of_hearing %} + {% bootstrap_field form.note_difficult_to_understand %} + {% bootstrap_field form.note_abusive_language %} + + {{ notes_formset.management_form }} +
+ {% for subform in notes_formset %} +
+
+ {{ subform.id.as_hidden }} + {{ subform.DELETE.as_hidden }} + + +
+
+ {% endfor %} +
+ +
+ +
+
+ + {% bootstrap_field form.source %} + +
+ {% if view.get_back_url %} + {% trans "Back" %} + {% endif %} + +
+
+{% endblock %} + +{% block extra_scripts %} + + +{% endblock %} diff --git a/castellum/subjects/templates/subjects/subject_base.html b/castellum/subjects/templates/subjects/subject_base.html index 4ea9bc96b5d5fc2878d956f383549a6afbad4b8b..fe88c72a2e7320ca46759923ed35bf9ff51bb728 100644 --- a/castellum/subjects/templates/subjects/subject_base.html +++ b/castellum/subjects/templates/subjects/subject_base.html @@ -24,22 +24,27 @@ {% endif %} + {% has_perm 'recruitment.change_attributeset' user as can_change_attributeset %} + {% if can_change_attributeset %} + + {% endif %} + {% has_perm 'subjects.change_subject' user as can_change_subject %} {% if can_change_subject %} - {% endif %} - - {% has_perm 'recruitment.change_attributeset' user as can_change_attributeset %} - {% if can_change_attributeset %} {% endif %} diff --git a/castellum/subjects/templates/subjects/subject_data_protection_form.html b/castellum/subjects/templates/subjects/subject_data_protection_form.html new file mode 100644 index 0000000000000000000000000000000000000000..bb7e36003305bc3a94ac9f2a1c3e71c90600df7a --- /dev/null +++ b/castellum/subjects/templates/subjects/subject_data_protection_form.html @@ -0,0 +1,68 @@ +{% extends base_template|default:"subjects/base.html" %} +{% load static i18n bootstrap4 subjects utils %} + +{% block title %} + {% trans "Edit subject" %} · {{ block.super }} +{% endblock %} + +{% block content %} +
+ {% for error in form.non_field_errors %} + + {% endfor %} + + {% csrf_token %} + +
+ {% trans 'Privacy level' %} + + {% bootstrap_field form.privacy_level show_label=False %} +
+ + {% get_db_consent_uploaded as db_consent_uploaded %} + {% if db_consent_uploaded %} +
+ {% trans 'Recruitment consent' %} + + {% with consent=object.confirmed_consent %} +
+ {% if consent %} + {{ consent.document }} {% if not consent.document.is_current %}({% trans 'outdated' %}){% endif %} +
+ {{ consent|display:'type' }}, + {% elif object.no_recruitment %} + {% trans 'No consent needed' %} + {% else %} + {% trans 'Missing consent' %} + {% endif %} +
+ {% endwith %} + + {% with consent=object.consent %} + {% if consent.status == consent.WAITING or not consent.document.is_current %} + {% bootstrap_field form.consent_type %} + {% bootstrap_field form.consent_status %} + {% endif %} + {% endwith %} +
+ {% endif %} + +
+ {% bootstrap_field form.export_requested %} + {% bootstrap_field form.to_be_deleted %} + {% bootstrap_field form.no_recruitment %} + +
+ +
+ {% if view.get_back_url %} + {% trans "Back" %} + {% endif %} + +
+
+{% endblock %} + +{% block extra_scripts %} + +{% endblock %} diff --git a/castellum/subjects/templates/subjects/subject_form.html b/castellum/subjects/templates/subjects/subject_form.html deleted file mode 100644 index 26cc68781fbb1e7f357c4f314dbe1cf263d61439..0000000000000000000000000000000000000000 --- a/castellum/subjects/templates/subjects/subject_form.html +++ /dev/null @@ -1,139 +0,0 @@ -{% extends base_template|default:"subjects/base.html" %} -{% load static i18n bootstrap4 subjects utils %} - -{% block title %} - {% trans "Edit subject" %} · {{ block.super }} -{% endblock %} - -{% block content %} - - -
- {% for error in form.non_field_errors %} - - {% endfor %} - - {% csrf_token %} - -
- {% trans 'Privacy level' %} - - {% bootstrap_field form.privacy_level show_label=False %} -
- - {% get_db_consent_uploaded as db_consent_uploaded %} - {% if db_consent_uploaded %} -
- {% trans 'Recruitment consent' %} - - {% with consent=object.confirmed_consent %} -
- {% if consent %} - {{ consent.document }} {% if not consent.document.is_current %}({% trans 'outdated' %}){% endif %} -
- {{ consent|display:'type' }}, - {% elif object.no_recruitment %} - {% trans 'No consent needed' %} - {% else %} - {% trans 'Missing consent' %} - {% endif %} -
- {% endwith %} - - {% with consent=object.consent %} - {% if consent.status == consent.WAITING or not consent.document.is_current %} - {% bootstrap_field form.consent_type %} - {% bootstrap_field form.consent_status %} - {% endif %} - {% endwith %} -
- {% endif %} - -
- {% trans 'Operational hints' %} - - {% bootstrap_field form.export_requested %} - {% bootstrap_field form.to_be_deleted %} - {% bootstrap_field form.no_recruitment %} - - -
- {% trans "Availability" %} - -
-
- {% bootstrap_field form.availability_monday %} -
-
- {% bootstrap_field form.availability_tuesday %} -
-
- {% bootstrap_field form.availability_wednesday %} -
-
- {% bootstrap_field form.availability_thursday %} -
-
- {% bootstrap_field form.availability_friday %} -
-
-
- - {% bootstrap_field form.not_available_until %} - -
- {% trans "Notes" %} - - {% bootstrap_field form.note_hard_of_hearing %} - {% bootstrap_field form.note_difficult_to_understand %} - {% bootstrap_field form.note_abusive_language %} - - {{ notes_formset.management_form }} -
- {% for subform in notes_formset %} -
-
- {{ subform.id.as_hidden }} - {{ subform.DELETE.as_hidden }} - - -
-
- {% endfor %} -
- -
- -
-
- - {% bootstrap_field form.source %} -
- -
- {% if view.get_back_url %} - {% trans "Back" %} - {% endif %} - -
-
-{% endblock %} - -{% block extra_scripts %} - - -{% endblock %} diff --git a/castellum/subjects/urls.py b/castellum/subjects/urls.py index a395f3c039648b59b20e2a6ba3b11a72ba9384b4..711274b40a6a95e03fd567e99babfbeeaf1a6a84 100644 --- a/castellum/subjects/urls.py +++ b/castellum/subjects/urls.py @@ -21,10 +21,12 @@ from django.urls import path +from .views import AdditionalInfoUpdateView from .views import AddToStudyView from .views import AttributeSetUpdateView from .views import ContactUpdateView from .views import CoverletterView +from .views import DataProtectionUpdateView from .views import GuardianSearchView from .views import MaintenanceAttributesView from .views import MaintenanceConsentView @@ -35,7 +37,6 @@ from .views import SubjectDeleteView from .views import SubjectDetailView from .views import SubjectExportView from .views import SubjectSearchView -from .views import SubjectUpdateView app_name = 'subjects' urlpatterns = [ @@ -43,9 +44,10 @@ urlpatterns = [ path('/', SubjectDetailView.as_view(), name='detail'), path('/delete/', SubjectDeleteView.as_view(), name='delete'), path('/export/', SubjectExportView.as_view(), name='export'), - path('/subject/', SubjectUpdateView.as_view(), name='subject'), path('/contact/', ContactUpdateView.as_view(), name='contact'), path('/attributes/', AttributeSetUpdateView.as_view(), name='attributeset'), + path('/data-protection/', DataProtectionUpdateView.as_view(), name='data-protection'), + path('/additional-info/', AdditionalInfoUpdateView.as_view(), name='additional-info'), path('/coverletter.docx', CoverletterView.as_view(), name='coverletter'), path( '/participations/', diff --git a/castellum/subjects/views.py b/castellum/subjects/views.py index 85d5ea82185f417c0cce7c46f277ae9dae55d101..b6a0002e3e205051abbca6933595e6ce19c98ec8 100644 --- a/castellum/subjects/views.py +++ b/castellum/subjects/views.py @@ -57,7 +57,8 @@ from castellum.studies.models import Study from castellum.utils.views import GetFormView from .forms import SubjectPrivacyLevelForm -from .mixins import BaseSubjectUpdateView +from .mixins import BaseAdditionalInfoUpdateView +from .mixins import BaseDataProtectionUpdateView from .mixins import SubjectMixin from .models import Consent from .models import ExportAnswer @@ -240,12 +241,7 @@ class SubjectExportView(SubjectMixin, PermissionRequiredMixin, DetailView): return redirect('subjects:export', self.object.pk) -class SubjectUpdateView(BaseSubjectUpdateView): - tab = 'subject' - - def get_success_url(self): - return reverse('subjects:subject', args=[self.object.pk]) - +class SubjectUpdateMixin: def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['base_template'] = 'subjects/subject_base.html' @@ -256,7 +252,21 @@ class SubjectUpdateView(BaseSubjectUpdateView): return super().form_valid(form, *args) -class ContactUpdateView(BaseContactUpdateView): +class DataProtectionUpdateView(SubjectUpdateMixin, BaseDataProtectionUpdateView): + tab = 'data-protection' + + def get_success_url(self): + return reverse('subjects:data-protection', args=[self.object.pk]) + + +class AdditionalInfoUpdateView(SubjectUpdateMixin, BaseAdditionalInfoUpdateView): + tab = 'additional-info' + + def get_success_url(self): + return reverse('subjects:additional-info', args=[self.object.pk]) + + +class ContactUpdateView(SubjectUpdateMixin, BaseContactUpdateView): tab = 'contact' def get_object(self): @@ -266,17 +276,8 @@ class ContactUpdateView(BaseContactUpdateView): def get_success_url(self): return reverse('subjects:contact', args=[self.object.subject.pk]) - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['base_template'] = 'subjects/subject_base.html' - return context - - def form_valid(self, form): - messages.success(self.request, _('Data has been saved.')) - return super().form_valid(form) - -class AttributeSetUpdateView(BaseAttributeSetUpdateView): +class AttributeSetUpdateView(SubjectUpdateMixin, BaseAttributeSetUpdateView): tab = 'attributeset' def get_object(self): @@ -289,15 +290,6 @@ class AttributeSetUpdateView(BaseAttributeSetUpdateView): def get_success_url(self): return reverse('subjects:attributeset', args=[self.object.subject.pk]) - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context['base_template'] = "subjects/subject_base.html" - return context - - def form_valid(self, form): - messages.success(self.request, _('Data has been saved.')) - return super().form_valid(form) - class ParticipationListView(SubjectMixin, PermissionRequiredMixin, ListView): tab = 'participations' diff --git a/tests/recruitment/views/test_subject_update_view.py b/tests/recruitment/views/test_subject_update_view.py index 4b7068e88b7e66daef1641459ab2f023310b3099..75569d8f7d1e0142f72d600c680cdd23486e894a 100644 --- a/tests/recruitment/views/test_subject_update_view.py +++ b/tests/recruitment/views/test_subject_update_view.py @@ -4,12 +4,24 @@ from castellum.recruitment.models import ParticipationRequest @pytest.mark.smoketest -def test_200(client, member, participation_request): +def test_data_protection_200(client, member, participation_request): participation_request.status = ParticipationRequest.NOT_CONTACTED participation_request.save() client.force_login(member) - response = client.get('/recruitment/{}/{}/update-subject/'.format( + response = client.get('/recruitment/{}/{}/update-data-protection/'.format( + participation_request.study.pk, participation_request.pk + )) + assert response.status_code == 200 + + +@pytest.mark.smoketest +def test_additional_info_200(client, member, participation_request): + participation_request.status = ParticipationRequest.NOT_CONTACTED + participation_request.save() + + client.force_login(member) + response = client.get('/recruitment/{}/{}/update-additional-info/'.format( participation_request.study.pk, participation_request.pk )) assert response.status_code == 200 diff --git a/tests/subjects/views/test_views.py b/tests/subjects/views/test_views.py index d564646b9eb688c14c8f7959f8fd792fcbc77c8c..77236448285817139a1e04df34dc5f70926afb81 100644 --- a/tests/subjects/views/test_views.py +++ b/tests/subjects/views/test_views.py @@ -51,19 +51,19 @@ def test_detail_with_attributeset_200(client, user, contact, attributeset): 'subject_manager', pytest.param('data_protection_coordinator', marks=pytest.mark.xfail(strict=True)), ]) -def test_subject_200(request, client, user_fixture, contact): +def test_data_protection_200(request, client, user_fixture, contact): user = request.getfixturevalue(user_fixture) client.force_login(user) - url = '/subjects/{}/subject/'.format(contact.subject.pk) + url = '/subjects/{}/data-protection/'.format(contact.subject.pk) response = client.get(url) assert response.status_code == 200 -def test_subject_post_valid(client, user, contact): +def test_data_protection_post_valid(client, user, contact): client.force_login(user) assert contact.subject.privacy_level == 0 - url = '/subjects/{}/subject/'.format(contact.subject.pk) + url = '/subjects/{}/data-protection/'.format(contact.subject.pk) response = client.post(url, { 'privacy_level': 1, 'form-TOTAL_FORMS': 0, @@ -75,10 +75,10 @@ def test_subject_post_valid(client, user, contact): assert contact.subject.privacy_level == 1 -def test_subject_post_invalid_privacy_level(client, user, contact): +def test_data_protection_post_invalid_privacy_level(client, user, contact): client.force_login(user) - url = '/subjects/{}/subject/'.format(contact.subject.pk) + url = '/subjects/{}/data-protection/'.format(contact.subject.pk) response = client.post(url, { 'privacy_level': 2, 'form-TOTAL_FORMS': 0, @@ -88,6 +88,20 @@ def test_subject_post_invalid_privacy_level(client, user, contact): assert b'Please choose lower privacy level for the subject.' in response.content +@pytest.mark.parametrize('user_fixture', [ + pytest.param('study_coordinator', marks=pytest.mark.xfail(strict=True)), + pytest.param('recruiter', marks=pytest.mark.xfail(strict=True)), + 'subject_manager', + pytest.param('data_protection_coordinator', marks=pytest.mark.xfail(strict=True)), +]) +def test_additional_info_200(request, client, user_fixture, contact): + user = request.getfixturevalue(user_fixture) + client.force_login(user) + url = '/subjects/{}/additional-info/'.format(contact.subject.pk) + response = client.get(url) + assert response.status_code == 200 + + @pytest.mark.smoketest @pytest.mark.parametrize('user_fixture', [ pytest.param('study_coordinator', marks=pytest.mark.xfail(strict=True)),