diff --git a/cadasta/organization/forms.py b/cadasta/organization/forms.py index bae2cf41c..8b1f01715 100644 --- a/cadasta/organization/forms.py +++ b/cadasta/organization/forms.py @@ -345,6 +345,17 @@ class Meta: fields = ['name', 'description', 'access', 'urls', 'questionnaire', 'contacts'] + def clean_questionnaire(self): + new_form = self.data.get('questionnaire') + current_form = self.initial.get('questionnaire') + + if (new_form is not None and new_form != current_form and + self.instance.has_records): + raise ValidationError( + _("Data has already been contributed to this project. To " + "ensure data integrity, uploading a new questionnaire is " + "disabled for this project.")) + def save(self, *args, **kwargs): new_form = self.data.get('questionnaire') original_file = self.data.get('original_file') @@ -357,7 +368,7 @@ def save(self, *args, **kwargs): original_file=original_file, project=self.instance ) - else: + elif new_form is not None and not self.instance.has_records: self.instance.current_questionnaire = '' return super().save(*args, **kwargs) diff --git a/cadasta/organization/tests/test_forms.py b/cadasta/organization/tests/test_forms.py index 27c4b329f..4655d9ab7 100644 --- a/cadasta/organization/tests/test_forms.py +++ b/cadasta/organization/tests/test_forms.py @@ -686,6 +686,65 @@ def test_replace_questionnaire(self): id=project.current_questionnaire ).xls_form.url == data['questionnaire']) + def test_replace_questionnaire_when_project_has_data(self): + project = ProjectFactory.create() + questionnaire = QuestionnaireFactory.create( + project=project, + xls_form=self._get_form('xls-form')) + + SpatialUnitFactory.create(project=project) + + data = { + 'name': 'New name', + 'questionnaire': self._get_form('xls-form-copy'), + 'access': project.access, + 'contacts-TOTAL_FORMS': 1, + 'contacts-INITIAL_FORMS': 0, + 'contacts-0-name': '', + 'contacts-0-email': '', + 'contacts-0-tel': '' + } + + form = forms.ProjectEditDetails( + instance=project, + data=data, + initial={'questionnaire': questionnaire.xls_form.url}) + + assert form.is_valid() is False + assert ("Data has already been contributed to this project. To " + "ensure data integrity, uploading a new questionnaire is " + "disabled for this project." in + form.errors.get('questionnaire')) + + def test_do_not_send_questionnaire_when_project_has_data(self): + project = ProjectFactory.create() + questionnaire = QuestionnaireFactory.create( + project=project, + xls_form=self._get_form('xls-form')) + + SpatialUnitFactory.create(project=project) + + data = { + 'name': 'New name', + 'access': project.access, + 'contacts-TOTAL_FORMS': 1, + 'contacts-INITIAL_FORMS': 0, + 'contacts-0-name': '', + 'contacts-0-email': '', + 'contacts-0-tel': '' + } + + form = forms.ProjectEditDetails( + instance=project, + data=data, + initial={'questionnaire': questionnaire.xls_form.url}) + + assert form.is_valid() is True + form.save() + project.refresh_from_db() + assert project.name == data['name'] + assert project.current_questionnaire == questionnaire.id + def test_delete_questionnaire(self): project = ProjectFactory.create() questionnaire = QuestionnaireFactory.create( diff --git a/cadasta/organization/tests/test_views_default_projects.py b/cadasta/organization/tests/test_views_default_projects.py index 19dacc173..ed6773cc1 100644 --- a/cadasta/organization/tests/test_views_default_projects.py +++ b/cadasta/organization/tests/test_views_default_projects.py @@ -935,6 +935,8 @@ class ProjectEditDetailsTest(ViewTestCase, UserTestCase, def setup_models(self): self.project = ProjectFactory.create(current_questionnaire='abc') + self.questionnaire = QuestionnaireFactory.create(project=self.project, + id='abc') def setup_url_kwargs(self): return { @@ -945,7 +947,11 @@ def setup_url_kwargs(self): def setup_template_context(self): return {'project': self.project, 'object': self.project, - 'form': forms.ProjectEditDetails(instance=self.project)} + 'form': forms.ProjectEditDetails( + instance=self.project, + initial={'questionnaire': self.questionnaire.xls_form.url, + 'original_file': self.questionnaire.original_file} + )} def test_get_with_authorized_user(self): user = UserFactory.create() @@ -956,6 +962,20 @@ def test_get_with_authorized_user(self): assert response.content == self.expected_content assert 'Select the questionnaire' in self.expected_content + def test_get_empty_questionnaire_with_authorized_user(self): + user = UserFactory.create() + assign_policies(user) + + self.project.current_questionnaire = '' + self.project.save() + + form = forms.ProjectEditDetails(instance=self.project) + + response = self.request(user=user) + assert response.status_code == 200 + assert response.content == self.render_content(form=form) + assert 'Select the questionnaire' in self.expected_content + def test_get_with_blocked_questionnaire_upload(self): user = UserFactory.create() assign_policies(user) @@ -1010,6 +1030,7 @@ def test_post_with_authorized_user(self): self.project.refresh_from_db() assert self.project.name == self.post_data['name'] assert self.project.description == self.post_data['description'] + assert self.project.current_questionnaire == '' def test_post_with_blocked_questionnaire_upload(self): SpatialUnitFactory.create(project=self.project) @@ -1023,6 +1044,20 @@ def test_post_with_blocked_questionnaire_upload(self): assert self.project.description != self.post_data['description'] assert self.project.current_questionnaire == 'abc' + def test_post_empty_questionnaire_with_blocked_questionnaire_upload(self): + SpatialUnitFactory.create(project=self.project) + user = UserFactory.create() + assign_policies(user) + response = self.request(user=user, method='POST', + post_data={'questionnaire': None}) + + assert response.status_code == 302 + assert self.expected_success_url in response.location + self.project.refresh_from_db() + assert self.project.name == self.post_data['name'] + assert self.project.description == self.post_data['description'] + assert self.project.current_questionnaire == 'abc' + def test_post_invalid_form(self): question = self.get_form('xls-form-invalid') user = UserFactory.create() diff --git a/cadasta/organization/views/default.py b/cadasta/organization/views/default.py index 46d095afb..a42a31636 100644 --- a/cadasta/organization/views/default.py +++ b/cadasta/organization/views/default.py @@ -651,16 +651,13 @@ def get_initial(self): return initial def post(self, *args, **kwargs): - if self.get_project().has_records: - return self.get(*args, **kwargs) - else: - try: - return super().post(*args, **kwargs) - except InvalidXLSForm as e: - form = self.get_form() - for err in e.errors: - form.add_error('questionnaire', err) - return self.form_invalid(form) + try: + return super().post(*args, **kwargs) + except InvalidXLSForm as e: + form = self.get_form() + for err in e.errors: + form.add_error('questionnaire', err) + return self.form_invalid(form) class ProjectEditPermissions(ProjectEdit, generic.UpdateView):