-
Valentin Groues authoredValentin Groues authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
forms.py 15.23 KiB
import datetime
from collections import OrderedDict
from django import forms
from django.forms import ModelForm, Form
from django.utils.dates import MONTHS
from models import Subject, Worker, Appointment, Visit, AppointmentType, ContactAttempt, AppointmentTypeLink
from models.constants import SUBJECT_TYPE_CHOICES, SCREENING_NUMBER_PREFIXES_FOR_TYPE
"""
Possible redundancy, but if need arises, contents of forms can be easily customized
"""
CURRENT_YEAR = datetime.datetime.now().year
YEAR_CHOICES = tuple(range(CURRENT_YEAR, CURRENT_YEAR - 120, -1))
FUTURE_YEAR_CHOICES = tuple(range(CURRENT_YEAR, CURRENT_YEAR + 5, 1))
DATEPICKER_DATE_ATTRS = {
'class': 'datepicker',
'data-date-format': 'yyyy-mm-dd',
'data-date-orientation': 'bottom'
}
DATETIMEPICKER_DATE_ATTRS = {
'class': 'datetimepicker',
'data-date-format': 'Y-MM-DD HH:mm',
}
START_YEAR_STATISTICS = 2015
APPOINTMENT_TYPES_FIELD_POSITION = 1
def validate_subject_nd_number(self, cleaned_data):
if cleaned_data['nd_number'] != "":
subjects_from_db = Subject.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")
class SubjectAddForm(ModelForm):
date_born = forms.DateField(label="Date of birth",
widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
required=False
)
datetime_contact_reminder = forms.DateTimeField(label="Contact on",
widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
required=False
)
class Meta:
model = Subject
fields = '__all__'
exclude = ['dead', 'resigned']
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
if user is None:
raise TypeError("User not defined")
self.user = Worker.get_by_user(user)
if self.user is None:
raise TypeError("Worker not defined for: " + user.username)
super(ModelForm, self).__init__(*args, **kwargs)
self.fields['screening_number'].required = False
def build_screening_number(self, cleaned_data):
screening_number = cleaned_data.get('screening_number', None)
if not screening_number:
prefix_screening_number = self.get_prefix_screening_number()
if prefix_screening_number is not None:
screening_number = get_new_screening_number(prefix_screening_number)
return screening_number
def clean(self):
cleaned_data = super(SubjectAddForm, self).clean()
screening_number = self.build_screening_number(cleaned_data)
if screening_number is not None:
cleaned_data['screening_number'] = screening_number
subjects_from_db = Subject.objects.filter(screening_number=screening_number)
if len(subjects_from_db) > 0:
self.add_error('screening_number', "Screening number already in use")
validate_subject_nd_number(self, cleaned_data)
return cleaned_data
def get_prefix_screening_number(self):
default_location = self.cleaned_data.get('default_location', None)
screening_number_prefix = None
if default_location is not None and default_location.prefix:
screening_number_prefix = default_location.prefix
else:
subject_type = self.cleaned_data.get('type', None)
if subject_type is not None:
screening_number_prefix = SCREENING_NUMBER_PREFIXES_FOR_TYPE[subject_type]
if screening_number_prefix is None:
return None
prefix_screening_number = screening_number_prefix + "-"
return prefix_screening_number
def get_new_screening_number(screening_number_prefix):
result_number = 0
subjects = Subject.objects.filter(screening_number__contains=screening_number_prefix)
for subject in subjects:
screening_numbers = subject.screening_number.split(";")
for screening_number in screening_numbers:
screening_number = screening_number.strip()
if screening_number.startswith(screening_number_prefix):
number = screening_number[len(screening_number_prefix):]
try:
result_number = max(result_number, int(number))
except ValueError:
pass
return screening_number_prefix + str(result_number + 1).zfill(3)
class SubjectDetailForm(ModelForm):
class Meta:
model = Subject
fields = '__all__'
class SubjectEditForm(ModelForm):
datetime_contact_reminder = forms.DateTimeField(label="Contact on",
widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
required=False
)
date_born = forms.DateField(label="Date of birth",
widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
required=False
)
def __init__(self, *args, **kwargs):
was_dead = kwargs.get('was_dead', False)
was_resigned = kwargs.get('was_resigned', False)
if 'was_resigned' in kwargs:
kwargs.pop('was_resigned')
if 'was_dead' in kwargs:
kwargs.pop('was_dead')
super(SubjectEditForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
if instance and instance.id:
self.fields['screening_number'].widget.attrs['readonly'] = True
if was_dead:
self.fields['dead'].disabled = True
if was_resigned:
self.fields['resigned'].disabled = True
def clean(self):
validate_subject_nd_number(self, self.cleaned_data)
class Meta:
model = Subject
fields = '__all__'
class WorkerAddForm(ModelForm):
class Meta:
model = Worker
exclude = ['appointments']
class WorkerDetailForm(ModelForm):
class Meta:
model = Worker
fields = '__all__'
class WorkerEditForm(ModelForm):
class Meta:
model = Worker
fields = '__all__'
class AppointmentDetailForm(ModelForm):
class Meta:
model = Appointment
fields = '__all__'
datetime_when = forms.DateTimeField(label='Appointment on (YYYY-MM-DD HH:MM)',
widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS)
)
class AppointmentEditForm(ModelForm):
class Meta:
model = Appointment
fields = '__all__'
exclude = ['appointment_types']
datetime_when = forms.DateTimeField(label='Appointment on (YYYY-MM-DD HH:MM)',
widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS)
)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
if user is None:
raise TypeError("User not defined")
self.user = Worker.get_by_user(user)
if self.user is None:
raise TypeError("Worker not defined for: " + user.username)
super(ModelForm, self).__init__(*args, **kwargs)
if 'instance' in kwargs:
initial_appointment_types = AppointmentTypeLink.objects.filter(appointment=kwargs['instance']).values_list(
'appointment_type', flat=True)
else:
initial_appointment_types = []
fields = OrderedDict()
for i, tuple in enumerate(self.fields.items()):
key, value = tuple
fields[key] = value
if i == APPOINTMENT_TYPES_FIELD_POSITION:
fields['appointment_types'] = forms.ModelMultipleChoiceField(required=False,
widget=forms.CheckboxSelectMultiple,
queryset=AppointmentType.objects.all(),
initial=initial_appointment_types)
self.fields = fields
def clean_location(self):
location = self.cleaned_data['location']
if self.user.locations.filter(id=location.id).count() == 0:
self.add_error('location', "You cannot create appointment for this location")
else:
return location
def save(self, commit=True):
appointment = super(AppointmentEditForm, self).save(commit)
AppointmentTypeLink.objects.filter(appointment=appointment).delete()
appointment_types = self.cleaned_data['appointment_types']
for appointment_type in appointment_types:
appointment_type_link = AppointmentTypeLink(appointment=appointment, appointment_type=appointment_type)
appointment_type_link.save()
return appointment
class AppointmentAddForm(ModelForm):
class Meta:
model = Appointment
exclude = ['status', 'appointment_types']
datetime_when = forms.DateTimeField(label='Appointment on (YYYY-MM-DD HH:MM)',
widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS)
)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
if user is None:
raise TypeError("User not defined")
self.user = Worker.get_by_user(user)
if self.user is None:
raise TypeError("Worker not defined for: " + user.username)
super(ModelForm, self).__init__(*args, **kwargs)
fields = OrderedDict()
for i, tuple in enumerate(self.fields.items()):
key, value = tuple
fields[key] = value
if i == APPOINTMENT_TYPES_FIELD_POSITION:
fields['appointment_types'] = forms.ModelMultipleChoiceField(required=False,
widget=forms.CheckboxSelectMultiple,
queryset=AppointmentType.objects.all(),
)
self.fields = fields
def clean_location(self):
location = self.cleaned_data['location']
if self.user.locations.filter(id=location.id).count() == 0:
self.add_error('location', "You cannot create appointment for this location")
else:
return location
def save(self, commit=True):
appointment = super(AppointmentAddForm, self).save(commit)
appointment_types = self.cleaned_data['appointment_types']
for appointment_type in appointment_types:
appointment_type_link = AppointmentTypeLink(appointment=appointment, appointment_type=appointment_type)
appointment_type_link.save()
return appointment
class VisitDetailForm(ModelForm):
datetime_begin = forms.DateField(label="Visit begins on",
widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
)
datetime_end = forms.DateField(label="Visit ends on",
widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
)
post_mail_sent = forms.RadioSelect()
appointment_types = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple,
queryset=AppointmentType.objects.all())
class Meta:
model = Visit
exclude = ['is_finished']
class VisitAddForm(ModelForm):
subject = forms.ModelChoiceField(queryset=Subject.objects.order_by('last_name', 'first_name'))
datetime_begin = forms.DateField(label="Visit begins on",
widget=forms.TextInput(attrs=DATEPICKER_DATE_ATTRS)
)
datetime_end = forms.DateField(label="Visit ends on",
widget=forms.TextInput(attrs=DATEPICKER_DATE_ATTRS)
)
appointment_types = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple,
queryset=AppointmentType.objects.all())
class Meta:
model = Visit
exclude = ['is_finished']
def clean(self):
super(VisitAddForm, self).clean()
if 'datetime_begin' not in self.cleaned_data or 'datetime_end' not in self.cleaned_data:
return
if self.cleaned_data['datetime_begin'] >= self.cleaned_data['datetime_end']:
self.add_error('datetime_begin', "Start date must be before end date")
self.add_error('datetime_end', "End date must be after start date")
class ContactAttemptForm(ModelForm):
datetime_when = forms.DateTimeField(label='When? (YYYY-MM-DD HH:MM)',
widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS)
)
class Meta:
model = ContactAttempt
fields = '__all__'
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
if user is None:
raise TypeError("User not defined")
self.user = Worker.get_by_user(user)
if self.user is None:
raise TypeError("Worker not defined for: " + user.username)
subject = kwargs.pop('subject', None)
super(ContactAttemptForm, self).__init__(*args, **kwargs)
self.fields['subject'].initial = subject.id
self.fields['subject'].disabled = True
self.fields['worker'].initial = self.user
class KitRequestForm(Form):
start_date = forms.DateField(label="From date",
widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
required=False
)
end_date = forms.DateField(label="End date",
widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
required=False
)
class StatisticsForm(Form):
def __init__(self, *args, **kwargs):
super(StatisticsForm, self).__init__(*args)
visit_choices = kwargs['visit_choices']
month = kwargs['month']
year = kwargs['year']
now = datetime.datetime.now()
year_now = now.year
number_of_years_for_statistics = year_now - START_YEAR_STATISTICS + 2
year_choices = [(START_YEAR_STATISTICS + i, START_YEAR_STATISTICS + i) for i in
range(0, number_of_years_for_statistics + 1)]
self.fields['month'] = forms.ChoiceField(choices=MONTHS.items(), initial=month)
self.fields['year'] = forms.ChoiceField(choices=year_choices, initial=year)
choices = [(-1, "all")]
choices.extend(SUBJECT_TYPE_CHOICES.items())
self.fields['subject_type'] = forms.ChoiceField(choices=choices, initial="-1")
self.fields['visit'] = forms.ChoiceField(choices=visit_choices, initial="-1")