Projet

Général

Profil

Télécharger (12,1 ko) Statistiques
| Branche: | Tag: | Révision:

calebasse / calebasse / agenda / forms.py @ ad0780e6

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

    
186
class DisablePatientAppointmentForm(UpdateAppointmentForm):
187

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

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

    
202

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

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

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

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

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

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

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

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

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

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

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