From 36423572389c7f6729e4098e93c8ee43a2567f26 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Thu, 30 Nov 2017 17:38:45 +0100
Subject: [PATCH] study introduced as a concept - every StudySubject should be
 assigned to study

---
 .../web/migrations/0071_auto_20171130_1607.py | 53 +++++++++++++++++++
 smash/web/models/__init__.py                  |  3 +-
 smash/web/models/constants.py                 |  6 ++-
 smash/web/models/study.py                     | 15 ++++++
 smash/web/models/study_subject.py             |  6 +++
 .../tests/forms/test_StudySubjectAddForm.py   |  6 ++-
 smash/web/tests/functions.py                  | 15 +++++-
 smash/web/tests/models/test_study.py          | 14 +++++
 smash/web/views/subject.py                    |  2 +
 9 files changed, 116 insertions(+), 4 deletions(-)
 create mode 100644 smash/web/migrations/0071_auto_20171130_1607.py
 create mode 100644 smash/web/models/study.py
 create mode 100644 smash/web/tests/models/test_study.py

diff --git a/smash/web/migrations/0071_auto_20171130_1607.py b/smash/web/migrations/0071_auto_20171130_1607.py
new file mode 100644
index 00000000..c757fdc1
--- /dev/null
+++ b/smash/web/migrations/0071_auto_20171130_1607.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-30 16:07
+from __future__ import unicode_literals
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+# noinspection PyUnusedLocal
+# noinspection PyPep8Naming
+def create_default_study(apps, schema_editor):
+    # We can't import the Study model directly as it may be a newer
+    # version than this migration expects. We use the historical version.
+    Study = apps.get_model("web", "Study")
+    study = Study.objects.create()
+    study.name = "New study"
+    study.save()
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('web', '0070_auto_20171128_1124'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Study',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=255, verbose_name=b'Name')),
+            ],
+        ),
+        migrations.AlterField(
+            model_name='studysubject',
+            name='subject',
+            field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='web.Subject',
+                                    verbose_name=b'Subject'),
+        ),
+        migrations.AddField(
+            model_name='studysubject',
+            name='study',
+            field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE,
+                                    to='web.Study', verbose_name=b'Study'),
+        ),
+        migrations.RunPython(create_default_study),
+        migrations.AlterField(
+            model_name='studysubject',
+            name='study',
+            field=models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, to='web.Study', verbose_name=b'Study'),
+            preserve_default=False,
+        ),
+
+    ]
diff --git a/smash/web/models/__init__.py b/smash/web/models/__init__.py
index 2b7f7dba..de19e31d 100644
--- a/smash/web/models/__init__.py
+++ b/smash/web/models/__init__.py
@@ -8,6 +8,7 @@ from flying_team import FlyingTeam
 from location import Location
 from appointment_type_link import AppointmentTypeLink
 from country import Country
+from study import Study
 from room import Room
 from visit import Visit
 from worker import Worker
@@ -25,6 +26,6 @@ from missing_subject import MissingSubject
 from inconsistent_subject import InconsistentSubject, InconsistentField
 
 
-__all__ = [FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room, Subject, StudySubject,
+__all__ = [Study, FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room, Subject, StudySubject,
            Visit, Worker, ContactAttempt, ConfigurationItem, MailTemplate, AppointmentTypeLink, MissingSubject,
            InconsistentSubject, InconsistentField, Country]
diff --git a/smash/web/models/constants.py b/smash/web/models/constants.py
index d2defa4d..fe6ade3b 100644
--- a/smash/web/models/constants.py
+++ b/smash/web/models/constants.py
@@ -76,4 +76,8 @@ REDCAP_TOKEN_CONFIGURATION_TYPE = "REDCAP_TOKEN_CONFIGURATION_TYPE"
 REDCAP_BASE_URL_CONFIGURATION_TYPE = "REDCAP_BASE_URL_CONFIGURATION_TYPE"
 
 COUNTRY_OTHER_ID = 1
-COUNTRY_AFGHANISTAN_ID = 2
\ No newline at end of file
+COUNTRY_AFGHANISTAN_ID = 2
+
+# id of the singleton Study,
+# TODO remove after allowing many studies per Smasch instance
+GLOBAL_STUDY_ID = 1
diff --git a/smash/web/models/study.py b/smash/web/models/study.py
new file mode 100644
index 00000000..469c5f4e
--- /dev/null
+++ b/smash/web/models/study.py
@@ -0,0 +1,15 @@
+# coding=utf-8
+from django.db import models
+
+
+class Study(models.Model):
+    class Meta:
+        app_label = 'web'
+
+    name = models.CharField(max_length=255, verbose_name='Name')
+
+    def __str__(self):
+        return "%s" % self.name
+
+    def __unicode__(self):
+        return "%s" % self.name
diff --git a/smash/web/models/study_subject.py b/smash/web/models/study_subject.py
index 7fdc2eac..29af9531 100644
--- a/smash/web/models/study_subject.py
+++ b/smash/web/models/study_subject.py
@@ -33,6 +33,12 @@ class StudySubject(models.Model):
                                 null=False,
                                 )
 
+    study = models.ForeignKey("web.Study",
+                              verbose_name='Study',
+                              editable=False,
+                              null=False,
+                              )
+
     postponed = models.BooleanField(choices=BOOL_CHOICES,
                                     verbose_name='Postponed',
                                     default=False
diff --git a/smash/web/tests/forms/test_StudySubjectAddForm.py b/smash/web/tests/forms/test_StudySubjectAddForm.py
index a417a5bb..21ff5486 100644
--- a/smash/web/tests/forms/test_StudySubjectAddForm.py
+++ b/smash/web/tests/forms/test_StudySubjectAddForm.py
@@ -3,7 +3,7 @@ import logging
 from web.forms import StudySubjectAddForm, get_new_screening_number
 from web.models.constants import SUBJECT_TYPE_CHOICES_CONTROL
 from web.tests import LoggedInWithWorkerTestCase
-from web.tests.functions import create_study_subject, create_subject
+from web.tests.functions import create_study_subject, create_subject, get_test_study
 
 logger = logging.getLogger(__name__)
 
@@ -14,6 +14,7 @@ class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
 
         location = self.worker.locations.all()[0]
         self.subject = create_subject()
+        self.study = get_test_study()
         self.sample_data = {
             'type': SUBJECT_TYPE_CHOICES_CONTROL,
             'default_location': location.id,
@@ -33,6 +34,7 @@ class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
         form = StudySubjectAddForm(data=form_data, user=self.user)
         form.is_valid()
         form.instance.subject_id = self.subject.id
+        form.instance.study_id = self.study.id
         self.assertTrue(form.is_valid())
         self.assertIsNone(form.fields['year_of_diagnosis'].initial)
         form.save()
@@ -50,6 +52,7 @@ class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
         form.is_valid()
         self.assertTrue(form.is_valid())
         form.instance.subject_id = self.subject.id
+        form.instance.study_id = self.study.id
         form.save()
 
         form_data['screening_number'] = "2"
@@ -66,6 +69,7 @@ class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
         form.is_valid()
         self.assertTrue(form.is_valid())
         form.instance.subject_id = self.subject.id
+        form.instance.study_id = self.study.id
         form.save()
 
         form_data['screening_number'] = "2"
diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py
index adb1eaf8..be71820b 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -4,7 +4,7 @@ import os
 from django.contrib.auth.models import User
 
 from web.models import Location, AppointmentType, StudySubject, Worker, Visit, Appointment, ConfigurationItem, Language, \
-    ContactAttempt, FlyingTeam, Availability, Subject
+    ContactAttempt, FlyingTeam, Availability, Subject, Study
 from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, REDCAP_BASE_URL_CONFIGURATION_TYPE, \
     SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, CONTACT_TYPES_PHONE, \
     MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID
@@ -23,6 +23,10 @@ def create_location(name="test"):
     return Location.objects.create(name=name)
 
 
+def create_study(name="test"):
+    return Study.objects.create(name=name)
+
+
 def get_test_location():
     locations = Location.objects.filter(name="test")
     if len(locations) > 0:
@@ -31,6 +35,14 @@ def get_test_location():
         return create_location()
 
 
+def get_test_study():
+    locations = Study.objects.filter(name="test-study")
+    if len(locations) > 0:
+        return locations[0]
+    else:
+        return create_study("test-study")
+
+
 def create_appointment_type():
     return AppointmentType.objects.create(
         code="C",
@@ -70,6 +82,7 @@ def create_study_subject(subject_id=1, subject=None):
         default_location=get_test_location(),
         type=SUBJECT_TYPE_CHOICES_CONTROL,
         screening_number="piotr's number" + str(subject_id),
+        study=get_test_study(),
         subject=subject
     )
 
diff --git a/smash/web/tests/models/test_study.py b/smash/web/tests/models/test_study.py
new file mode 100644
index 00000000..9c9e02f7
--- /dev/null
+++ b/smash/web/tests/models/test_study.py
@@ -0,0 +1,14 @@
+import logging
+
+from django.test import TestCase
+
+from web.tests.functions import create_study
+
+logger = logging.getLogger(__name__)
+
+
+class StudyTests(TestCase):
+    def test_image_img(self):
+        study = create_study()
+
+        self.assertTrue(study.name in str(study))
diff --git a/smash/web/views/subject.py b/smash/web/views/subject.py
index 53ceafe6..d8d04046 100644
--- a/smash/web/views/subject.py
+++ b/smash/web/views/subject.py
@@ -4,6 +4,7 @@ import logging
 from django.contrib import messages
 from django.shortcuts import redirect, get_object_or_404
 
+from ..models.constants import GLOBAL_STUDY_ID
 from . import wrap_response
 from ..forms import StudySubjectAddForm, StudySubjectEditForm, VisitDetailForm, SubjectEditForm, SubjectAddForm
 from ..models import StudySubject, MailTemplate, Worker
@@ -31,6 +32,7 @@ def subject_add(request):
         if study_subject_form.is_valid() and subject_form.is_valid():
             subject = subject_form.save()
             study_subject_form.instance.subject_id = subject.id
+            study_subject_form.instance.study_id = GLOBAL_STUDY_ID
             study_subject_form.save()
             messages.add_message(request, messages.SUCCESS, 'Subject created')
             return redirect('web.views.subject_edit', id=study_subject_form.instance.id)
-- 
GitLab