Project

General

Profile

Download (12.1 KB) Statistics
| Branch: | Tag: | Revision:

calebasse / calebasse / agenda / forms.py @ 1f4ae3b3

1
# -*- coding: utf-8 -*-
2

    
3
from datetime import datetime, timedelta, time
4

    
5
from django import forms
6
from django.db.models import Q
7
from django.utils.translation import ugettext_lazy as _
8

    
9
from ..dossiers.models import PatientRecord
10
from ..personnes.models import Worker
11
from ..actes.models import Act
12
from ..ressources.models import ActType
13
from ..middleware.request import get_request
14

    
15
from ajax_select import make_ajax_field
16
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
17
from models import Event, EventWithAct, EventType
18

    
19
class BaseForm(forms.ModelForm):
20
    date = forms.DateField(label=u'Date', localize=True)
21
    time = forms.TimeField(label=u'Heure de début')
22
    duration = forms.CharField(label=u'Durée',
23
            help_text=u'en minutes; vous pouvez utiliser la roulette de votre souris.')
24
    participants = make_ajax_field(EventWithAct, 'participants', 'worker-or-group', True)
25

    
26

    
27
class NewAppointmentForm(BaseForm):
28
    patient = AutoCompleteSelectMultipleField('patientrecord')
29

    
30
    class Meta:
31
        model = EventWithAct
32
        fields = (
33
                'start_datetime',
34
                'date',
35
                'time',
36
                'duration',
37
                'patient',
38
                'participants',
39
                'ressource',
40
                'act_type',
41
                'description',
42
                'recurrence_periodicity',
43
                'recurrence_end_date'
44
        )
45
        widgets = {
46
                'start_datetime': forms.HiddenInput,
47
        }
48

    
49
    def __init__(self, instance, service=None, **kwargs):
50
        self.service = None
51
        super(NewAppointmentForm, self).__init__(instance=instance, **kwargs)
52
        self.fields['date'].css = 'datepicker'
53
        self.fields['participants'].required = True
54
        self.fields['time'].required = False
55
        self.fields['duration'].required = False
56
        if service:
57
            self.service = service
58
            self.special_types = [str(act.id) for act in ActType.objects.filter(Q(name__iexact='courriel')
59
                                                                                | Q(name__iexact='telephone')
60
                                                                                | Q(name__iexact='téléphone'))]
61
            self.fields['participants'].queryset = \
62
                    Worker.objects.for_service(service)
63
            self.fields['patient'].queryset = \
64
                    PatientRecord.objects.for_service(service)
65
            self.fields['act_type'].queryset = \
66
                    ActType.objects.for_service(service) \
67
                    .order_by('name')
68

    
69
    def clean_time(self):
70
        act_type = self.data.get('act_type')
71
        # act type is available as raw data from the post request
72
        if act_type in self.special_types:
73
            return time(8, 0)
74
        if self.cleaned_data['time']:
75
            return self.cleaned_data['time']
76
        raise forms.ValidationError(_(u'This field is required.'))
77

    
78
    def clean_duration(self):
79
        act_type = self.data.get('act_type')
80
        if act_type in self.special_types:
81
            return 10
82
        if self.cleaned_data['duration']:
83
            duration = self.cleaned_data['duration']
84
            try:
85
                duration = int(duration)
86
                if duration <= 0:
87
                    raise ValueError
88
                return duration
89
            except ValueError:
90
                raise forms.ValidationError(u'Le champ doit contenir uniquement des chiffres')
91
        raise forms.ValidationError(_(u'This field is required.'))
92

    
93
    def clean_patient(self):
94
        patients = self.cleaned_data['patient']
95
        if patients:
96
            return [patient for patient in PatientRecord.objects.filter(pk__in=patients)]
97

    
98
    def clean(self):
99
        cleaned_data = super(NewAppointmentForm, self).clean()
100
        if not cleaned_data.get('recurrence_periodicity'):
101
            cleaned_data['recurrence_end_date'] = None
102
        if cleaned_data.has_key('date') and cleaned_data.has_key('time'):
103
            cleaned_data['start_datetime'] = datetime.combine(cleaned_data['date'],
104
                    cleaned_data['time'])
105
        if 'patient' in cleaned_data and isinstance(cleaned_data['patient'], list):
106
            # nasty trick to store the list of patients and pass the form
107
            # validation
108
            cleaned_data['patients'] = cleaned_data['patient']
109
            cleaned_data['patient'] = cleaned_data['patient'][0]
110
        return cleaned_data
111

    
112
    def save(self, commit=True):
113

    
114
        patients = self.cleaned_data.pop('patients')
115
        for patient in patients:
116
            appointment = forms.save_instance(self, self._meta.model(), commit=False)
117
            appointment.start_datetime = datetime.combine(self.cleaned_data['date'],
118
                                                          self.cleaned_data['time'])
119
            appointment.end_datetime = appointment.start_datetime + timedelta(
120
                minutes=self.cleaned_data['duration'])
121
            appointment.creator = get_request().user
122
            appointment.clean()
123
            if commit:
124
                appointment.patient = patient
125
                appointment.save()
126
                self.save_m2m()
127
                appointment.services = [self.service]
128

    
129
class UpdateAppointmentForm(NewAppointmentForm):
130

    
131
    patient = make_ajax_field(EventWithAct, 'patient', 'patientrecord', False)
132

    
133
    def clean_patient(self):
134
        return self.cleaned_data['patient']
135

    
136
    def save(self, commit=True):
137
        appointment = super(NewAppointmentForm, self).save(commit=False)
138
        appointment.start_datetime = datetime.combine(self.cleaned_data['date'],
139
                    self.cleaned_data['time'])
140
        appointment.end_datetime = appointment.start_datetime + timedelta(
141
                minutes=self.cleaned_data['duration'])
142
        appointment.creator = get_request().user
143
        appointment.clean()
144
        if commit:
145
            appointment.save()
146
            self.save_m2m()
147
            appointment.services = [self.service]
148
        return appointment
149

    
150

    
151
class UpdatePeriodicAppointmentForm(UpdateAppointmentForm):
152
    patient = make_ajax_field(EventWithAct, 'patient', 'patientrecord', False)
153
    recurrence_periodicity = forms.ChoiceField(label=u"Périodicité",
154
            choices=Event.PERIODICITIES, required=True)
155

    
156
    def clean(self):
157
        '''
158
            Check that reccurrency bound dates
159
            won't exclude already_billed acts.
160
        '''
161
        cleaned_data = super(UpdatePeriodicAppointmentForm, self).clean()
162
        start_datetime = cleaned_data.get('start_datetime')
163
        if start_datetime:
164
            acts = Act.objects.filter(
165
                Q(parent_event=self.instance,
166
                    already_billed=True, date__lt=start_datetime) | \
167
                Q(parent_event__exception_to=self.instance,
168
                    already_billed=True, date__lt=start_datetime))
169
            if acts:
170
                self._errors['start_datetime'] = self.error_class([
171
                    u"La date de début doit être antérieure au premier acte déja facturé de la récurrence"])
172
        recurrence_end_date = cleaned_data.get('recurrence_end_date')
173
        if recurrence_end_date:
174
            acts = Act.objects.filter(
175
                Q(parent_event=self.instance,
176
                    already_billed=True, date__gt=recurrence_end_date) | \
177
                Q(parent_event__exception_to=self.instance,
178
                    already_billed=True, date__gt=recurrence_end_date))
179
            if acts:
180
                self._errors['recurrence_end_date'] = self.error_class([
181
                    u"La date de fin doit être postérieure au dernier acte déja facturé de la récurrence"])
182
        return cleaned_data
183

    
184
class DisablePatientAppointmentForm(UpdateAppointmentForm):
185

    
186
    def __init__(self, instance, service=None, **kwargs):
187
        super(DisablePatientAppointmentForm, self).__init__(instance,
188
                service, **kwargs)
189
        if instance and instance.pk:
190
            self.fields['patient'].required = False
191
            self.fields['patient'].widget.attrs['disabled'] = 'disabled'
192

    
193
    def clean_patient(self):
194
        instance = getattr(self, 'instance', None)
195
        if instance:
196
            return instance.patient
197
        else:
198
            return self.cleaned_data.get('patient', None)
199

    
200

    
201
class NewEventForm(BaseForm):
202
    title = forms.CharField(label=u"Complément de l'intitulé", max_length=32, required=False)
203

    
204
    class Meta:
205
        model = Event
206
        fields = (
207
                'start_datetime',
208
                'title',
209
                'date',
210
                'time',
211
                'duration',
212
                'ressource',
213
                'participants',
214
                'event_type',
215
                'services',
216
                'description',
217
                'recurrence_periodicity',
218
                'recurrence_end_date',
219
        )
220
        widgets = {
221
                'start_datetime': forms.HiddenInput,
222
                'services': forms.CheckboxSelectMultiple,
223
        }
224

    
225
    def __init__(self, instance, service=None, **kwargs):
226
        self.service = service
227
        super(NewEventForm, self).__init__(instance=instance, **kwargs)
228
        self.fields['date'].css = 'datepicker'
229
        self.fields['event_type'].queryset = \
230
                    EventType.objects.exclude(id=1).exclude(id=3).order_by('rank', 'label')
231

    
232
    def clean_duration(self):
233
        duration = self.cleaned_data['duration']
234
        try:
235
            return int(duration)
236
        except:
237
            raise forms.ValidationError('Veuillez saisir un entier')
238

    
239
    def save(self, commit=True):
240
        event = super(NewEventForm, self).save(commit=False)
241
        event.start_datetime = datetime.combine(self.cleaned_data['date'],
242
                    self.cleaned_data['time'])
243
        event.end_datetime = event.start_datetime + timedelta(
244
                minutes=self.cleaned_data['duration'])
245
        event.creator = get_request().user
246
        event.clean()
247
        if commit:
248
            event.save()
249
            event.services = [self.service]
250
        return event
251

    
252
    def clean(self):
253
        cleaned_data = super(NewEventForm, self).clean()
254
        if cleaned_data.has_key('date') and cleaned_data.has_key('time'):
255
            cleaned_data['start_datetime'] = datetime.combine(cleaned_data['date'],
256
                    cleaned_data['time'])
257
        if not cleaned_data.get('recurrence_periodicity'):
258
            cleaned_data['recurrence_end_date'] = None
259
        event_type = cleaned_data.get('event_type')
260
        if event_type and event_type.id == 4 and not cleaned_data.get('title'): # 'Autre'
261
            self._errors['title'] = self.error_class([
262
                            u"Ce champ est obligatoire pour les événements de type « Autre »."])
263
        return cleaned_data
264

    
265
class UpdatePeriodicEventForm(NewEventForm):
266
    recurrence_periodicity = forms.ChoiceField(label=u"Périodicité",
267
            choices=Event.PERIODICITIES, required=True)
268

    
269
class UpdateEventForm(NewEventForm):
270
    class Meta(NewEventForm.Meta):
271
        fields = (
272
                'start_datetime',
273
                'title',
274
                'date',
275
                'time',
276
                'duration',
277
                'ressource',
278
                'participants',
279
                'event_type',
280
                'services',
281
        )
282

    
283
class PeriodicEventsSearchForm(forms.Form):
284
    start_date = forms.DateField(localize=True, required = False)
285
    end_date = forms.DateField(required=False, localize=True)
286

    
287
    event_type = forms.MultipleChoiceField(
288
            choices=(
289
                (0, 'Rendez-vous patient'),
290
                (1, 'Évènement')),
291
            widget=forms.CheckboxSelectMultiple,
292
            initial=[0,1])
293
    no_end_date = forms.BooleanField(label=u'Sans date de fin', required=False)
294
    patient = AutoCompleteSelectField('patientrecord', required=False, help_text='')
295
    worker = AutoCompleteSelectField('worker', required=False, help_text='')
296

    
297
    def clean(self):
298
        cleaned_data = super(PeriodicEventsSearchForm, self).clean()
299
        if cleaned_data.get('start_date') and cleaned_data.get('end_date'):
300
            if cleaned_data['start_date'] > cleaned_data['end_date']:
301
                raise forms.ValidationError(u'La date de début doit être antérieure à la date de fin')
302
        return cleaned_data
(5-5/10)