Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
appointment_form.py 6.32 KiB
import logging
from collections import OrderedDict

from django import forms
from django.forms import ModelForm

from web.models.worker_study_role import WORKER_STAFF
from web.forms.forms import DATETIMEPICKER_DATE_ATTRS, APPOINTMENT_TYPES_FIELD_POSITION
from web.models import Appointment, Worker, AppointmentTypeLink, AppointmentType
from web.views.notifications import get_filter_locations

logger = logging.getLogger(__name__)


class AppointmentForm(ModelForm):
    datetime_when = forms.DateTimeField(label='Appointment on',
                                        widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS)
                                        )

    def __init__(self, *args, **kwargs):
        super(AppointmentForm, self).__init__(*args, **kwargs)
        self.fields['worker_assigned'].queryset = Worker.get_workers_by_worker_type(WORKER_STAFF).filter(
            locations__in=get_filter_locations(self.user)).distinct().order_by('first_name', 'last_name')


class AppointmentDetailForm(AppointmentForm):
    class Meta:
        model = Appointment
        fields = '__all__'


class AppointmentEditForm(AppointmentForm):
    class Meta:
        model = Appointment
        fields = '__all__'
        exclude = ['appointment_types']

    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(AppointmentEditForm, 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
        self.fields['location'].queryset = get_filter_locations(self.user)

    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)
        # if appointment date change, remove appointment_type links
        if 'datetime_when' in self.changed_data:
            AppointmentTypeLink.objects.filter(appointment=appointment).delete()
            appointment_type_links = []
        else:
            appointment_type_links = AppointmentTypeLink.objects.filter(appointment=appointment).all()
        appointment_types_from_links = []
        appointment_types = self.cleaned_data['appointment_types']
        for appointment_type_link in appointment_type_links:
            if appointment_type_link.appointment_type not in appointment_types:
                # we delete appointment links for appointments types that have been removed
                appointment_type_link.delete()
            else:
                appointment_types_from_links.append(appointment_type_link.appointment_type)
        for appointment_type in appointment_types:
            if appointment_type not in appointment_types_from_links:
                # we create new appointment links for appointments types that have been added
                appointment_type_link = AppointmentTypeLink(appointment=appointment,
                                                            appointment_type=appointment_type)
                appointment_type_link.save()
        return appointment


class AppointmentAddForm(AppointmentForm):
    class Meta:
        model = Appointment
        exclude = ['status', 'appointment_types']

    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(AppointmentAddForm, 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(),
                                                                             )
        fields['worker_assigned'].widget.attrs = {'class': 'search_worker_availability'}
        fields['datetime_when'].widget.attrs = {'class': 'start_date'}
        fields['length'].widget.attrs = {'class': 'appointment_duration'}

        self.fields = fields
        self.fields['location'].queryset = get_filter_locations(self.user)

    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