diff --git a/factories/formlibrary_models.py b/factories/formlibrary_models.py index b49d57199..c37477649 100644 --- a/factories/formlibrary_models.py +++ b/factories/formlibrary_models.py @@ -32,3 +32,4 @@ class Meta: name = 'Custom Form A' organization = SubFactory(Organization) + public = {'org': False, 'url': False} diff --git a/formlibrary/migrations/0012_remove_customform_public.py b/formlibrary/migrations/0012_remove_customform_public.py new file mode 100644 index 000000000..ddafae055 --- /dev/null +++ b/formlibrary/migrations/0012_remove_customform_public.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.3 on 2018-08-06 15:08 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('formlibrary', '0011_set_customform_public'), + ] + + operations = [ + migrations.RemoveField( + model_name='customform', + name='public', + ), + ] diff --git a/formlibrary/migrations/0013_auto_20180807_0436.py b/formlibrary/migrations/0013_auto_20180807_0436.py new file mode 100644 index 000000000..1dd450ca4 --- /dev/null +++ b/formlibrary/migrations/0013_auto_20180807_0436.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.3 on 2018-08-07 11:36 +from __future__ import unicode_literals + +import django.contrib.postgres.fields.jsonb +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('formlibrary', '0012_remove_customform_public'), + ] + + operations = [ + migrations.AddField( + model_name='customform', + name='public', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, help_text='Public information with the structure:{org: (bool), url: (bool)}', null=True), + ), + migrations.AlterField( + model_name='customform', + name='fields', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True), + ), + ] diff --git a/formlibrary/migrations/0014_set_customform_public.py b/formlibrary/migrations/0014_set_customform_public.py new file mode 100644 index 000000000..e3596e9a1 --- /dev/null +++ b/formlibrary/migrations/0014_set_customform_public.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.3 on 2018-08-07 14:02 +from __future__ import unicode_literals + +from django.db import migrations +from ..models import CustomForm + + +def set_form_public(apps, schema_editor): + CustomForm.objects.filter(is_public=True).update( + public={'org': True, 'url': False}) + + +class Migration(migrations.Migration): + + dependencies = [ + ('formlibrary', '0013_auto_20180807_0436'), + ] + + operations = [ + migrations.RunPython(set_form_public), + ] diff --git a/formlibrary/models.py b/formlibrary/models.py index c2c705175..0c3579edf 100755 --- a/formlibrary/models.py +++ b/formlibrary/models.py @@ -1,11 +1,14 @@ from __future__ import unicode_literals +import json import uuid from django.db import models from django.contrib import admin from django.contrib.postgres.fields import JSONField +from django.core.exceptions import ValidationError from django.utils import timezone +from voluptuous import Schema, Required from workflow.models import WorkflowLevel1, SiteProfile, WorkflowLevel2, Office, AdminLevelOne, Organization from indicators.models import DisaggregationValue, Indicator @@ -193,14 +196,14 @@ class CustomFormFieldAdmin(admin.ModelAdmin): class CustomForm(models.Model): - PUBLIC_ALL = 'all' - PUBLIC_URL = 'url' - - PUBLIC_CHOICES = ( - (PUBLIC_ALL, 'ALL'), - (PUBLIC_URL, 'URL'), - ) - + PUBLIC_ALL = 'all' # deprecated + PUBLIC_URL = 'url' # deprecated + + PUBLIC_CHOICES = ( # deprecated + (PUBLIC_ALL, 'ALL'), # deprecated + (PUBLIC_URL, 'URL'), # deprecated + ) # deprecated + STATUS_ARCHIVED = 'archived' STATUS_NEW = 'new' STATUS_PUBLISHED = 'published' @@ -217,11 +220,11 @@ class CustomForm(models.Model): form_uuid = models.CharField(max_length=255, verbose_name='CustomForm UUID', default=uuid.uuid4, unique=True) description = models.TextField(null=True, blank=True) validations = models.CharField(max_length=500, null=True, blank=True) - fields = JSONField(null=True) + fields = JSONField(blank=True, null=True) is_public = models.BooleanField(default=0) default_global = models.BooleanField(default=0) organization = models.ForeignKey(Organization, default=1) - public = models.CharField(choices=PUBLIC_CHOICES, max_length=5, blank=True, null=True) + public = JSONField(blank=True, null=True, help_text="Public information with the structure:{org: (bool), url: (bool)}") workflowlevel1 = models.ForeignKey(WorkflowLevel1, blank=True, null=True) silo_id = models.IntegerField(default=0) status = models.CharField(blank=True, null=True, max_length=15, default=STATUS_NEW, choices=STATUS_CHOICES) @@ -233,8 +236,24 @@ class CustomForm(models.Model): class Meta: ordering = ('name',) + def _validate_public(self, public): + schema = Schema({ + Required('org'): bool, + Required('url'): bool + }) + return schema(public) + + def clean_fields(self, exclude=None): + super(CustomForm, self).clean_fields(exclude=exclude) + if not self.is_template and self.public is not None: + try: + self.public = self._validate_public(self.public) + except Exception as e: + raise ValidationError(e) + # on save add create date or update edit date def save(self, *args, **kwargs): + self.full_clean() if self.create_date == None: self.create_date = timezone.now() self.edit_date = timezone.now() diff --git a/formlibrary/tests/__init__.py b/formlibrary/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/formlibrary/tests/test_models.py b/formlibrary/tests/test_models.py new file mode 100644 index 000000000..2207b1a68 --- /dev/null +++ b/formlibrary/tests/test_models.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +from django.core.exceptions import ValidationError +from django.test import TestCase, tag + +import factories +from formlibrary.models import CustomForm + + +@tag('pkg') +class CustomFormTest(TestCase): + def setUp(self): + self.organization = factories.Organization() + self.user = factories.User() + + def test_save_without_public_info(self): + custom_form = CustomForm( + organization=self.organization, + name="Humanitec's Survey", + fields="{}", + public={} + ) + + self.assertRaises(ValidationError, custom_form.save) + + def test_save_without_public_org_info(self): + custom_form = CustomForm( + organization=self.organization, + name="Humanitec's Survey", + fields="{}", + public={'url': True} + ) + + self.assertRaises(ValidationError, custom_form.save) + + def test_save_without_public_url_info(self): + custom_form = CustomForm( + organization=self.organization, + name="Humanitec's Survey", + fields="{}", + public={'org': True} + ) + + self.assertRaises(ValidationError, custom_form.save) + + def test_save_with_public_info(self): + custom_form = CustomForm.objects.create( + organization=self.organization, + name="Humanitec's Survey", + fields="{}", + public={'org': True, 'url': True} + ) + + self.assertEqual(custom_form.name, "Humanitec's Survey") + self.assertEqual(custom_form.public, {'org': True, 'url': True})