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