Project

General

Profile

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

calebasse / calebasse / agenda / forms.py @ a2e49cca

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
        if self.cleaned_data['time']:
71
            return self.cleaned_data['time']
72

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

    
79
    def clean_duration(self):
80
        if self.cleaned_data['duration']:
81
            duration = self.cleaned_data['duration']
82
            try:
83
                duration = int(duration)
84
                if duration <= 0:
85
                    raise ValueError
86
                return duration
87
            except ValueError:
88
                raise forms.ValidationError(u'Le champ doit contenir uniquement des chiffres')
89

    
90
        act_type = self.data.get('act_type')
91
        if act_type in self.special_types:
92
            return 10
93
        raise forms.ValidationError(_(u'This field is required.'))
94

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

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

    
114
    def save(self, commit=True):
115

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

    
131
class UpdateAppointmentForm(NewAppointmentForm):
132

    
133
    patient = make_ajax_field(EventWithAct, 'patient', 'patientrecord', False)
134

    
135
    def clean_patient(self):
136
        return self.cleaned_data['patient']
137

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

    
152

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

    
158
    def clean(self):
159
        cleaned_data = super(UpdatePeriodicAppointmentForm, self).clean()
160
        '''If one act not new in the reccurrence, we prevent to modify the
161
        start date or the recurrence_periodicity since this could trigger act
162
        deletion'''
163
        start_datetime = cleaned_data.get('start_datetime')
164
        if start_datetime and start_datetime != self.instance.start_datetime \
165
                and self.instance.one_act_not_new():
166
            self._errors['start_datetime'] = self.error_class([
167
                u"La date de début ne peut-être modifiée car un acte de la récurrence est pointé"])
168
#       FIXME
169
#        recurrence_periodicity = cleaned_data.get('recurrence_periodicity')
170
#        if recurrence_periodicity and recurrence_periodicity != str(self.instance.recurrence_periodicity) \
171
#                and self.instance.one_act_not_new():
172
#            self._errors['recurrence_periodicity'] = self.error_class([
173
#                u"La récurrence ne peut-être modifiée car un acte de la récurrence est pointé"])
174
        '''We check that the end date is posterior to the last act not new'''
175
        recurrence_end_date = cleaned_data.get('recurrence_end_date')
176
        if recurrence_end_date and recurrence_end_date != self.instance.recurrence_end_date \
177
                and self.instance.one_act_not_new():
178
            last = self.instance.last_act_not_new()
179
            if last and last.date > recurrence_end_date:
180
                self._errors['recurrence_end_date'] = self.error_class([
181
                    u"La date de fin doit être postérieure au dernier acte pointé de la récurrence (%s)" % last])
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)