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