Skip to content
Snippets Groups Projects
Commit 89058edd authored by Piotr Gawron's avatar Piotr Gawron
Browse files

add/edit form for study subject use customized set of fields for given study

parent c8f57af0
No related branches found
No related tags found
1 merge request!101Resolve "list of subjects should contain columns dependent on the study"
import datetime
import logging
import re
from collections import OrderedDict
from django import forms
from django.forms import ModelForm, Form
from django.utils.dates import MONTHS
from models import Study, StudyColumns
from web.models import Subject, StudySubject, Worker, Appointment, Visit, AppointmentType, ContactAttempt, \
AppointmentTypeLink, \
Availability, Holiday
......@@ -41,11 +43,16 @@ logger = logging.getLogger(__name__)
def validate_subject_nd_number(self, cleaned_data):
if cleaned_data['nd_number'] != "":
subjects_from_db = StudySubject.objects.filter(nd_number=cleaned_data['nd_number'])
if subjects_from_db:
if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
self.add_error('nd_number', "ND number already in use")
if self.study.columns.nd_number:
nd_number = cleaned_data['nd_number']
if nd_number != "":
if re.match('ND[0-9][0-9][0-9][0-9]', nd_number) is None:
self.add_error('nd_number', "Invalid ND number")
else:
subjects_from_db = StudySubject.objects.filter(nd_number=nd_number, study=self.study)
if subjects_from_db:
if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
self.add_error('nd_number', "ND number already in use")
def validate_subject_country(self, cleaned_data):
......@@ -59,11 +66,12 @@ def validate_subject_resign_reason(self, cleaned_data):
def validate_subject_mpower_number(self, cleaned_data):
if cleaned_data['mpower_id'] != "":
subjects_from_db = StudySubject.objects.filter(mpower_id=cleaned_data['mpower_id'])
if subjects_from_db:
if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
self.add_error('mpower_id', "mPower number already in use")
if self.study.columns.mpower_id:
if cleaned_data['mpower_id'] != "":
subjects_from_db = StudySubject.objects.filter(mpower_id=cleaned_data['mpower_id'])
if subjects_from_db:
if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
self.add_error('mpower_id', "mPower number already in use")
def get_worker_from_args(kwargs):
......@@ -83,6 +91,65 @@ def get_study_from_args(kwargs):
return study
def prepare_study_subject_fields(fields, study):
if study.columns.default_location:
fields['default_location'].required = True
else:
del fields['default_location']
if study.columns.type:
fields['type'].required = True
else:
del fields['type']
if not study.columns.nd_number:
del fields['nd_number']
if not study.columns.datetime_contact_reminder:
del fields['datetime_contact_reminder']
if not study.columns.postponed:
del fields['postponed']
if not study.columns.flying_team:
del fields['flying_team']
if not study.columns.mpower_id:
del fields['mpower_id']
if not study.columns.comments:
del fields['comments']
if not study.columns.referral:
del fields['referral']
if not study.columns.diagnosis:
del fields['diagnosis']
if not study.columns.year_of_diagnosis:
del fields['year_of_diagnosis']
if not study.columns.information_sent:
del fields['information_sent']
if not study.columns.pd_in_family:
del fields['pd_in_family']
if not study.columns.resigned and 'resigned' in fields:
del fields['resigned']
if not study.columns.resign_reason and 'resign_reason' in fields:
del fields['resign_reason']
def validate_subject_screening_number(self, cleaned_data):
if self.study.columns.resign_reason:
subjects_from_db = StudySubject.objects.filter(screening_number=cleaned_data["screening_number"],
study=self.study)
if len(subjects_from_db) > 0:
self.add_error('screening_number', "Screening number already in use")
class StudySubjectAddForm(ModelForm):
datetime_contact_reminder = forms.DateTimeField(label="Contact on",
widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
......@@ -99,7 +166,7 @@ class StudySubjectAddForm(ModelForm):
self.study = get_study_from_args(kwargs)
super(ModelForm, self).__init__(*args, **kwargs)
self.fields['screening_number'].required = False
prepare_study_subject_fields(fields=self.fields, study=self.study)
def save(self, commit=True):
self.instance.study_id = self.study.id
......@@ -116,12 +183,9 @@ class StudySubjectAddForm(ModelForm):
def clean(self):
cleaned_data = super(StudySubjectAddForm, self).clean()
screening_number = self.build_screening_number(cleaned_data)
if screening_number is not None:
if screening_number is not None and self.study.columns.screening_number:
cleaned_data['screening_number'] = screening_number
subjects_from_db = StudySubject.objects.filter(screening_number=screening_number)
if len(subjects_from_db) > 0:
self.add_error('screening_number', "Screening number already in use")
validate_subject_screening_number(self, cleaned_data)
validate_subject_nd_number(self, cleaned_data)
validate_subject_mpower_number(self, cleaned_data)
return cleaned_data
......@@ -178,6 +242,11 @@ class StudySubjectEditForm(ModelForm):
instance = getattr(self, 'instance', None)
if instance and instance.id:
self.fields['screening_number'].widget.attrs['readonly'] = True
if instance and instance.study_id:
self.study = Study.objects.filter(id=instance.study_id)[0]
else:
self.study = Study(columns=StudyColumns())
if was_resigned:
self.fields['resigned'].disabled = True
......
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-12-01 10:34
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('web', '0072_auto_20171201_1013'),
]
operations = [
migrations.AlterField(
model_name='studysubject',
name='default_location',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Location', verbose_name=b'Default appointment location'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-12-01 10:38
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('web', '0073_auto_20171201_1034'),
]
operations = [
migrations.AlterField(
model_name='studysubject',
name='default_location',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Location', verbose_name=b'Default appointment location'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-12-01 12:52
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('web', '0074_auto_20171201_1038'),
]
operations = [
migrations.AlterField(
model_name='studysubject',
name='nd_number',
field=models.CharField(blank=True, max_length=25, verbose_name=b'ND number'),
),
migrations.AlterField(
model_name='studysubject',
name='screening_number',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name=b'Screening number'),
),
migrations.AlterField(
model_name='studysubject',
name='type',
field=models.CharField(blank=True, choices=[(b'P', b'PATIENT'), (b'C', b'CONTROL')], max_length=1, null=True, verbose_name=b'Type'),
),
]
......@@ -50,28 +50,31 @@ class StudySubject(models.Model):
)
type = models.CharField(max_length=1,
choices=SUBJECT_TYPE_CHOICES.items(),
verbose_name='Type'
verbose_name='Type',
null=True,
blank=True
)
default_location = models.ForeignKey(Location,
verbose_name='Default appointment location',
null=True,
blank=True
)
flying_team = models.ForeignKey("web.FlyingTeam",
verbose_name='Default flying team location (if applicable)',
null=True, blank=True
null=True,
blank=True
)
screening_number = models.CharField(max_length=50,
unique=True,
verbose_name='Screening number', blank=False, null=False
verbose_name='Screening number',
blank=True,
null=True
)
nd_number = models.CharField(max_length=25,
blank=True,
verbose_name='ND number',
validators=[
RegexValidator('^(ND[0-9]{4}|)$',
message="ND number should look as follows: NDxxxx")]
)
mpower_id = models.CharField(max_length=20,
blank=True,
......
......@@ -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, get_test_study
from web.tests.functions import create_study_subject, create_subject, get_test_study, create_empty_study
logger = logging.getLogger(__name__)
......@@ -27,6 +27,11 @@ class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
form.is_valid()
self.assertTrue(form.is_valid())
def test_validation_for_study_without_columns(self):
form = StudySubjectAddForm(data=self.sample_data, user=self.user, study=create_empty_study())
form.is_valid()
self.assertTrue(form.is_valid())
def test_invalid(self):
form_data = self.sample_data
form_data['screening_number'] = "123"
......
......@@ -38,7 +38,7 @@ class StudySubjectEditFormTests(LoggedInWithWorkerTestCase):
study_subject2.save()
self.sample_data['nd_number'] = "ND0124"
edit_form = StudySubjectEditForm(self.sample_data)
edit_form = StudySubjectEditForm(self.sample_data, instance=self.study_subject)
save_status = edit_form.is_valid()
self.assertTrue("nd_number" in edit_form.errors)
......
......@@ -28,6 +28,28 @@ def create_study(name="test"):
return Study.objects.create(name=name, columns=study_columns)
def create_empty_study(name="test"):
study_columns = StudyColumns.objects.create(
postponed=False,
datetime_contact_reminder=False,
type=False,
default_location=False,
flying_team=False,
screening_number=False,
nd_number=False,
mpower_id=False,
comments=False,
referral=False,
diagnosis=False,
year_of_diagnosis=False,
information_sent=False,
pd_in_family=False,
resigned=False,
resign_reason=False
)
return Study.objects.create(name=name, columns=study_columns)
def get_test_location():
locations = Location.objects.filter(name="test")
if len(locations) > 0:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment