Skip to content
Snippets Groups Projects
forms.py 9.49 KiB
Newer Older
import datetime
from django.forms import ModelForm, Form
from django.utils.dates import MONTHS
from web.models import Appointment, AppointmentType, AppointmentTypeLink, \
Jacek Lebioda's avatar
Jacek Lebioda committed
    Availability, ContactAttempt, FlyingTeam, Holiday, Item, \
    StudySubject, Room, Worker, Visit, VoucherType, VoucherTypePrice
from web.models.constants import SUBJECT_TYPE_CHOICES
Jacek Lebioda's avatar
Jacek Lebioda committed
Possible redundancy, but if need arises, contents of forms can be easily customized
DATE_FORMAT_TIME = "%H:%M"
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))
Jacek Lebioda's avatar
Jacek Lebioda committed
DATEPICKER_DATE_ATTRS = {
    'class': 'datepicker',
    'data-date-format': 'yyyy-mm-dd',
Jacek Lebioda's avatar
Jacek Lebioda committed
    'data-date-orientation': 'bottom'
}
DATETIMEPICKER_DATE_ATTRS = {
    'class': 'datetimepicker',
    'data-date-format': 'Y-MM-DD HH:mm',
TIMEPICKER_DATE_ATTRS = {
    'class': 'datetimepicker',
    'data-date-format': 'HH:mm',
    'data-date-stepping': 15,
}
START_YEAR_STATISTICS = 2015
APPOINTMENT_TYPES_FIELD_POSITION = 1
def get_worker_from_args(kwargs):
    user = kwargs.pop('user', None)
    if user is None:
        raise TypeError("User not defined")
    result = Worker.get_by_user(user)
    if result is None:
        raise TypeError("Worker not defined for: " + user.username)
    return result


class VisitDetailForm(ModelForm):
Jacek Lebioda's avatar
Jacek Lebioda committed
    datetime_begin = forms.DateField(label="Visit begins on",
                                     widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
                                     )
Jacek Lebioda's avatar
Jacek Lebioda committed
    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())
    def __init__(self, *args, **kwargs):
        super(VisitDetailForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance.is_finished: #set form as readonly
            for key in self.fields.keys():
                self.fields[key].widget.attrs['readonly'] = True


        model = Visit
        exclude = ['is_finished', 'visit_number']
Piotr Matyjaszyk's avatar
Piotr Matyjaszyk committed

Piotr Matyjaszyk's avatar
Piotr Matyjaszyk committed
class VisitAddForm(ModelForm):
    subject = forms.ModelChoiceField(
        queryset=StudySubject.objects.order_by('subject__last_name', 'subject__first_name'))
Jacek Lebioda's avatar
Jacek Lebioda committed
    datetime_begin = forms.DateField(label="Visit begins on",
                                     widget=forms.TextInput(attrs=DATEPICKER_DATE_ATTRS)
                                     )
Jacek Lebioda's avatar
Jacek Lebioda committed
    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())
Piotr Matyjaszyk's avatar
Piotr Matyjaszyk committed
    class Meta:
        model = Visit
        exclude = ['is_finished', 'visit_number']

    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 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")


class AvailabilityAddForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(AvailabilityAddForm, self).__init__(*args, **kwargs)
        self.fields['person'].widget.attrs['readonly'] = True
    
    available_from = forms.TimeField(label="Available from",
                                     widget=forms.TimeInput(TIMEPICKER_DATE_ATTRS),
                                     initial="8:00",
                                     )
    available_till = forms.TimeField(label="Available until",
                                     widget=forms.TimeInput(TIMEPICKER_DATE_ATTRS),
                                     initial="17:00",
                                     )

    class Meta:
        model = Availability
        fields = '__all__'

    def clean(self):
        worker = Worker.objects.get(id=self.cleaned_data["person"].id)
        availabilities = worker.availability_set.all()
        for availability in availabilities:
            validate_availability_conflict(self, self.cleaned_data, availability)


class AvailabilityEditForm(ModelForm):
    available_from = forms.TimeField(label="Available from",
                                     widget=forms.TimeInput(TIMEPICKER_DATE_ATTRS),
                                     )
    available_till = forms.TimeField(label="Available until",
                                     widget=forms.TimeInput(TIMEPICKER_DATE_ATTRS),
                                     )

    class Meta:
        model = Availability
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(ModelForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance is not None:
            self.availability_id = instance.id
        self.fields['person'].disabled = True

    def clean(self):
        worker = Worker.objects.get(id=self.cleaned_data["person"].id)
        availabilities = worker.availability_set.all()
        for availability in availabilities:
Piotr Gawron's avatar
Piotr Gawron committed
            if availability.id != self.availability_id:
                validate_availability_conflict(self, self.cleaned_data, availability)


def validate_availability_conflict(self, cleaned_data, availability):
    start_hour = self.cleaned_data.get("available_from", None)
    end_hour = self.cleaned_data.get("available_till", None)
    if availability.day_number == self.cleaned_data.get("day_number", None) and \
            ((start_hour <= availability.available_from < end_hour) or
Piotr Gawron's avatar
Piotr Gawron committed
             (start_hour < availability.available_till <= end_hour) or
             (availability.available_from <= start_hour < availability.available_till) or
             (availability.available_from < end_hour <= availability.available_till)):
        error = "User has defined availability for this day that overlaps: " + availability.available_from.strftime(
            DATE_FORMAT_TIME) + ", " + availability.available_till.strftime(DATE_FORMAT_TIME)
        self.add_error('day_number', error)
        self.add_error('available_from', error)
        self.add_error('available_till', error)
Jacek Lebioda's avatar
Jacek Lebioda committed
class ItemForm(ModelForm):
    class Meta:
        model = Item
        fields = "__all__"


class FlyingTeamAddForm(ModelForm):
    class Meta:
        model = FlyingTeam
        fields = "__all__"


Jacek Lebioda's avatar
Jacek Lebioda committed
class FlyingTeamEditForm(ModelForm):
    class Meta:
        model = FlyingTeam
        fields = "__all__"


class HolidayAddForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(HolidayAddForm, self).__init__(*args, **kwargs)
        self.fields['person'].widget.attrs['readonly'] = True
    datetime_start = forms.DateTimeField(widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
                                         initial=datetime.datetime.now().replace(hour=8, minute=0),
                                         )
    datetime_end = forms.DateTimeField(widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
                                       initial=datetime.datetime.now().replace(hour=17, minute=0),
                                       )

    class Meta:
        model = Holiday
        fields = '__all__'

    def clean(self):
        worker = Worker.objects.get(id=self.cleaned_data["person"].id)
        availabilities = worker.availability_set.all()
        for availability in availabilities:
            validate_availability_conflict(self, self.cleaned_data, availability)
Jacek Lebioda's avatar
Jacek Lebioda committed
class RoomForm(ModelForm):
    class Meta:
        model = Room
        fields = '__all__'