Project

General

Profile

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

calebasse / calebasse / agenda / views.py @ 0cbf950f

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

    
3
import datetime
4
from itertools import chain
5

    
6
from django.contrib import messages
7
from django.db.models import Q
8
from django.shortcuts import redirect, get_object_or_404
9
from django.http import HttpResponseRedirect, HttpResponse
10
from django.conf import settings
11

    
12
from calebasse.cbv import TemplateView, CreateView, UpdateView
13
from calebasse.agenda.models import Event, EventType, EventWithAct
14
from calebasse.personnes.models import TimeTable, Holiday
15
from calebasse.agenda.appointments import get_daily_appointments, get_daily_usage
16
from calebasse.personnes.models import Worker
17
from calebasse.ressources.models import WorkerType, Room
18
from calebasse.actes.validation import (get_acts_of_the_day,
19
        get_days_with_acts_not_locked)
20
from calebasse.actes.validation_states import VALIDATION_STATES
21
from calebasse.actes.models import Act, ValidationMessage
22
from calebasse.actes.validation import (automated_validation, unlock_all_acts_of_the_day)
23
from calebasse import cbv
24

    
25
from forms import (NewAppointmentForm, NewEventForm, UpdatePeriodicAppointmentForm,
26
        DisablePatientAppointmentForm, UpdateAppointmentForm,
27
        UpdateEventForm, PeriodicEventsSearchForm)
28

    
29
def redirect_today(request, service):
30
    '''If not date is given we redirect on the agenda for today'''
31
    return redirect('agenda', date=datetime.date.today().strftime('%Y-%m-%d'),
32
            service=service)
33

    
34

    
35
class AgendaHomepageView(TemplateView):
36
    template_name = 'agenda/index.html'
37
    cookies_to_clear = []
38

    
39
    def post(self, request, *args, **kwargs):
40
        acte_id = request.POST.get('event-id')
41
        try:
42
            event = EventWithAct.objects.get(id=acte_id)
43
            event = event.today_occurrence(self.date)
44
            act = event.act
45
            if not act.validation_locked:
46
                state_name = request.POST.get('act_state')
47
                act.save()
48
                act.set_state(state_name, request.user)
49
        except Act.DoesNotExist:
50
            pass
51
        return HttpResponseRedirect('#acte-frame-'+acte_id)
52

    
53
    def get_context_data(self, **kwargs):
54
        context = super(AgendaHomepageView, self).get_context_data(**kwargs)
55

    
56
        context['workers_types'] = []
57
        workers = Worker.objects.filter(enabled=True).select_related() \
58
                .prefetch_related('services')
59
        worker_by_type = {}
60
        for worker in workers:
61
            workers_for_type = worker_by_type.setdefault(worker.type, [])
62
            workers_for_type.append(worker)
63
        for worker_type, workers_for_type in worker_by_type.iteritems():
64
            context['workers_types'].append(
65
                    {'type': worker_type.name, 'workers': workers_for_type })
66
        context['workers'] = workers
67
        context['disponibility_start_times'] = range(8, 20)
68

    
69
        return context
70

    
71

    
72
class AgendaServiceActivityView(TemplateView, cbv.ServiceViewMixin):
73
    template_name = 'agenda/service-activity.html'
74
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
75

    
76
    def get_context_data(self, **kwargs):
77
        context = super(AgendaServiceActivityView, self).get_context_data(**kwargs)
78

    
79
        appointments_times = dict()
80
        events = Event.objects.for_today(self.date) \
81
                .exclude(event_type_id=1) \
82
                .filter(services=self.service) \
83
                .order_by('start_datetime', 'id') \
84
                .select_related() \
85
                .prefetch_related('participants', 'exceptions')
86
        eventswithact = EventWithAct.objects.for_today(self.date) \
87
                .filter(services=self.service) \
88
                .order_by('start_datetime', 'id') \
89
                .select_related() \
90
                .prefetch_related('participants', 'exceptions')
91
        events = [ e.today_occurrence(self.date) for e in events ] \
92
             + [ e.today_occurrence(self.date) for e in eventswithact ]
93
        for event in events:
94
            start_datetime = event.start_datetime.strftime("%H:%M")
95
            if not appointments_times.has_key(start_datetime):
96
                appointments_times[start_datetime] = dict()
97
                appointments_times[start_datetime]['row'] = 0
98
                appointments_times[start_datetime]['appointments'] = []
99
            appointment = dict()
100
            length = event.end_datetime - event.start_datetime
101
            if length.seconds:
102
                length = length.seconds / 60
103
                appointment['length'] = "%sm" % length
104
            if event.event_type_id == 1:
105
                appointment['type'] = 1
106
                appointment['label'] = event.patient.display_name
107
                appointment['paper_id'] = event.patient.paper_id
108
                appointment['act'] = event.act_type.name
109
                appointment['state'] = event.act.get_state()
110
                appointment['absent'] = event.act.is_absent()
111
            else:
112
                appointment['type'] = 2
113
                if event.event_type.label == 'Autre' and event.title:
114
                    appointment['label'] = event.title
115
                else:
116
                    appointment['label'] = '%s - %s' % (event.event_type.label,
117
                                                        event.title)
118
            appointment['participants'] = event.participants.filter(worker__enabled=True)
119
            appointment['len_participants'] = len(appointment['participants'])
120
            appointment['workers_absent'] = event.get_missing_participants()
121
            appointments_times[start_datetime]['row'] += 1
122
            appointments_times[start_datetime]['appointments'].append(appointment)
123
        context['appointments_times'] = sorted(appointments_times.items())
124
        return context
125

    
126

    
127
class NewAppointmentView(cbv.ReturnToObjectMixin, cbv.ServiceFormMixin, CreateView):
128
    model = EventWithAct
129
    form_class = NewAppointmentForm
130
    template_name = 'agenda/new-appointment.html'
131
    success_url = '..'
132
    success_msg = u'Rendez-vous enregistré avec succès.'
133
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
134

    
135
    def get_initial(self):
136
        initial = super(NewAppointmentView, self).get_initial()
137
        initial['start_datetime'] = self.date
138
        initial['date'] = self.date
139
        initial['participants'] = self.request.GET.getlist('participants')
140
        initial['time'] = self.request.GET.get('time')
141
        initial['room'] = self.request.GET.get('room')
142
        return initial
143

    
144
    def get_form_kwargs(self):
145
        kwargs = super(NewAppointmentView, self).get_form_kwargs()
146
        kwargs['service'] = self.service
147
        return kwargs
148

    
149
    def form_valid(self, form):
150
        messages.add_message(self.request, messages.INFO, self.success_msg)
151
        return super(NewAppointmentView, self).form_valid(form)
152

    
153

    
154
class TodayOccurrenceMixin(object):
155
    def get_object(self, queryset=None):
156
        o = super(TodayOccurrenceMixin, self).get_object(queryset)
157
        return o.today_occurrence(self.date)
158

    
159

    
160
class BaseAppointmentView(UpdateView):
161
    model = EventWithAct
162
    form_class = UpdateAppointmentForm
163
    template_name = 'agenda/update-rdv.html'
164
    success_url = '..'
165
    cookies_to_clear = []
166

    
167
    def get_initial(self):
168
        initial = super(BaseAppointmentView, self).get_initial()
169
        initial['start_datetime'] = self.date
170
        initial['date'] = self.object.start_datetime.date()
171
        initial['time'] = self.object.start_datetime.time()
172
        time = self.object.end_datetime - self.object.start_datetime
173
        if time:
174
            time = time.seconds / 60
175
        else:
176
            time = 0
177
        initial['duration'] = time
178
        initial['participants'] = self.object.participants.values_list('id', flat=True)
179
        return initial
180

    
181
    def get_form_kwargs(self):
182
        kwargs = super(BaseAppointmentView, self).get_form_kwargs()
183
        kwargs['service'] = self.service
184
        return kwargs
185

    
186

    
187
class UpdateAppointmentView(TodayOccurrenceMixin, BaseAppointmentView):
188

    
189
    def get_form_class(self):
190
        if self.object.exception_to and not self.object.exception_to.canceled:
191
            return DisablePatientAppointmentForm
192
        else:
193
            return self.form_class
194

    
195

    
196
class UpdatePeriodicAppointmentView(BaseAppointmentView):
197
    form_class = UpdatePeriodicAppointmentForm
198
    template_name = 'agenda/new-appointment.html'
199

    
200

    
201
class NewEventView(CreateView):
202
    model = Event
203
    form_class = NewEventForm
204
    template_name = 'agenda/new-event.html'
205
    success_url = '..'
206
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
207

    
208
    def get_initial(self):
209
        initial = super(NewEventView, self).get_initial()
210
        initial['start_datetime'] = self.date
211
        initial['date'] = self.date
212
        initial['participants'] = self.request.GET.getlist('participants')
213
        initial['time'] = self.request.GET.get('time')
214
        initial['event_type'] = 2
215
        initial['room'] = self.request.GET.get('room')
216
        if not initial.has_key('services'):
217
            initial['services'] = [self.service]
218
        return initial
219

    
220
    def get_form_kwargs(self):
221
        kwargs = super(NewEventView, self).get_form_kwargs()
222
        kwargs['service'] = self.service
223
        return kwargs
224

    
225
    def form_valid(self, form):
226
        messages.add_message(self.request, messages.INFO, u'Evénement enregistré avec succès.')
227
        return super(NewEventView, self).form_valid(form)
228

    
229

    
230
class BaseEventView(UpdateView):
231
    model = Event
232
    form_class = UpdateEventForm
233
    template_name = 'agenda/update-event.html'
234
    success_url = '..'
235
    cookies_to_clear = []
236

    
237
    def get_initial(self):
238
        initial = super(BaseEventView, self).get_initial()
239
        initial['start_datetime'] = self.date
240
        initial['date'] = self.object.start_datetime.date()
241
        initial['time'] = self.object.start_datetime.time()
242
        time = self.object.end_datetime - self.object.start_datetime
243
        if time:
244
            time = time.seconds / 60
245
        else:
246
            time = 0
247
        initial['duration'] = time
248
        initial['participants'] = self.object.participants.values_list('id', flat=True)
249
        return initial
250

    
251
    def get_form_kwargs(self):
252
        kwargs = super(BaseEventView, self).get_form_kwargs()
253
        kwargs['service'] = self.service
254
        return kwargs
255

    
256

    
257
class UpdateEventView(TodayOccurrenceMixin, BaseEventView):
258
    pass
259

    
260

    
261
class UpdatePeriodicEventView(BaseEventView):
262
    form_class = NewEventForm
263
    template_name = 'agenda/new-event.html'
264

    
265

    
266
class DeleteOccurrenceView(TodayOccurrenceMixin, cbv.DeleteView):
267
    model = Event
268
    success_url = '..'
269
    cookies_to_clear = []
270

    
271
    def delete(self, request, *args, **kwargs):
272
        self.object = self.get_object()
273
        if self.object.event_type == 1 and self.object.act.id \
274
                and not self.object.act.is_billed:
275
            self.object.act.delete()
276
        self.object.delete()
277

    
278
        return HttpResponse(status=204)
279

    
280
class DeleteEventView(cbv.DeleteView):
281
    """
282
    TODO: Remove this class
283
    """
284
    model = Event
285
    success_url = '..'
286
    cookies_to_clear = []
287

    
288
    def delete(self, request, *args, **kwargs):
289
        super(DeleteEventView, self).delete(request, *args, **kwargs)
290
        return HttpResponse(status=204)
291

    
292
class AgendaServiceActValidationView(TemplateView):
293
    template_name = 'agenda/act-validation.html'
294
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
295

    
296
    def acts_of_the_day(self):
297
        acts = list(Act.objects \
298
                .filter(date=self.date, patient__service=self.service) \
299
                .select_related() \
300
                .prefetch_related('doctors',
301
                        'patient__patientcontact',
302
                        'actvalidationstate_set__previous_state') \
303
                .order_by('time'))
304
        event_ids = [ a.parent_event_id for a in acts if a.parent_event_id ]
305
        events = EventWithAct.objects.for_today(self.date) \
306
                .filter(patient__service=self.service) \
307
                .exclude(id__in=event_ids)
308
        events = [ event.today_occurrence(self.date) for event in events ]
309
        acts += [ event.act for event in events if event ]
310
        return sorted(acts, key=lambda a: (a.time or datetime.time.min, a.id))
311

    
312
    def post(self, request, *args, **kwargs):
313
        if 'unlock-all' in request.POST:
314
            #TODO: check that the user is authorized
315
            unlock_all_acts_of_the_day(self.date, self.service)
316
            ValidationMessage(validation_date=self.date,
317
                who=request.user, what='Déverrouillage',
318
                service=self.service).save()
319
        else:
320
            acte_id = request.POST.get('acte-id')
321
            try:
322
                act = Act.objects.get(id=acte_id)
323
                if 'lock' in request.POST or 'unlock' in request.POST:
324
                    #TODO: check that the user is authorized
325
                    act.validation_locked = 'lock' in request.POST
326
                    act.save()
327
                else:
328
                    state_name = request.POST.get('act_state')
329
                    act.set_state(state_name, request.user)
330
            except Act.DoesNotExist:
331
                pass
332
            return HttpResponseRedirect('#acte-frame-'+acte_id)
333
        return HttpResponseRedirect('')
334

    
335
    def get_context_data(self, **kwargs):
336
        context = super(AgendaServiceActValidationView, self).get_context_data(**kwargs)
337
        authorized_lock = True # is_authorized_for_locking(get_request().user)
338
        validation_msg = ValidationMessage.objects.\
339
            filter(validation_date=self.date, service=self.service).\
340
            order_by('-when')[:3]
341
        acts_of_the_day = self.acts_of_the_day()
342
        actes = list()
343
        for act in acts_of_the_day:
344
            if not act.id:
345
                if act.date < datetime.date(2013, 1, 1):
346
                    continue
347
                else:
348
                    act.save()
349
            state = act.get_state()
350
            display_name = None
351
            if state :
352
                display_name = VALIDATION_STATES[state.state_name]
353
                if not state.previous_state_id and state.state_name == 'NON_VALIDE':
354
                    state = None
355
            actes.append((act, state, display_name))
356
        validation_states = dict(VALIDATION_STATES)
357
        if self.service.name != 'CMPP' and \
358
                'ACT_DOUBLE' in validation_states:
359
            validation_states.pop('ACT_DOUBLE')
360
        vs = [('VALIDE', 'Présent')]
361
        validation_states.pop('VALIDE')
362
        validation_states.pop('ACT_LOST')
363
        validation_states = vs + sorted(validation_states.items(), key=lambda tup: tup[0])
364
        context['validation_states'] = validation_states
365
        context['actes'] = actes
366
        context['validation_msg'] = validation_msg
367
        context['authorized_lock'] = authorized_lock
368
        return context
369

    
370

    
371
class AutomatedValidationView(TemplateView):
372
    template_name = 'agenda/automated-validation.html'
373

    
374
    def post(self, request, *args, **kwargs):
375
        automated_validation(self.date, self.service,
376
            request.user)
377
        ValidationMessage(validation_date=self.date,
378
            who=request.user, what='Validation automatique',
379
            service=self.service).save()
380
        return HttpResponseRedirect('..')
381

    
382
    def get_context_data(self, **kwargs):
383
        context = super(AutomatedValidationView, self).get_context_data(**kwargs)
384
        request = self.request
385
        (nb_acts_total, nb_acts_validated, nb_acts_double,
386
        nb_acts_abs_non_exc, nb_acts_abs_exc, nb_acts_abs_inter, nb_acts_annul_nous,
387
        nb_acts_annul_famille, nb_acts_reporte, nb_acts_abs_ess_pps,
388
        nb_acts_enf_hosp, nb_acts_losts) = \
389
            automated_validation(self.date, self.service,
390
                request.user, commit = False)
391

    
392
        nb_acts_not_validated = nb_acts_double + \
393
            nb_acts_abs_non_exc + \
394
            nb_acts_abs_exc + \
395
            nb_acts_abs_inter + \
396
            nb_acts_annul_nous + \
397
            nb_acts_annul_famille + \
398
            nb_acts_reporte + \
399
            nb_acts_abs_ess_pps + \
400
            nb_acts_enf_hosp + \
401
            nb_acts_losts
402
        context.update({
403
            'nb_acts_total': nb_acts_total,
404
            'nb_acts_validated': nb_acts_validated,
405
            'nb_acts_not_validated': nb_acts_not_validated,
406
            'nb_acts_double': nb_acts_double,
407
            'nb_acts_abs_non_exc': nb_acts_abs_non_exc,
408
            'nb_acts_abs_exc': nb_acts_abs_exc,
409
            'nb_acts_abs_inter': nb_acts_abs_inter,
410
            'nb_acts_annul_nous': nb_acts_annul_nous,
411
            'nb_acts_annul_famille': nb_acts_annul_famille,
412
            'nb_acts_reporte': nb_acts_reporte,
413
            'nb_acts_abs_ess_pps': nb_acts_abs_ess_pps,
414
            'nb_acts_enf_hosp': nb_acts_enf_hosp,
415
            'nb_acts_losts': nb_acts_losts})
416
        return context
417

    
418
class UnlockAllView(CreateView):
419
    pass
420

    
421

    
422
class AgendasTherapeutesView(AgendaHomepageView):
423
    template_name = 'agenda/agendas-therapeutes.html'
424
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
425

    
426
    def get_context_data(self, **kwargs):
427
        context = super(AgendasTherapeutesView, self).get_context_data(**kwargs)
428

    
429
        time_tables = TimeTable.objects.select_related('worker'). \
430
                filter(services=self.service). \
431
                for_today(self.date). \
432
                order_by('start_date')
433
        holidays = Holiday.objects.select_related('worker') \
434
                .for_period(self.date, self.date) \
435
                .order_by('start_date') \
436
                .select_related()
437
        events = Event.objects.for_today(self.date) \
438
                .exclude(event_type_id=1) \
439
                .filter(services=self.service) \
440
                .order_by('start_datetime') \
441
                .select_related() \
442
                .prefetch_related('services',
443
                        'exceptions',
444
                        'participants')
445
        eventswithact = EventWithAct.objects.for_today(self.date) \
446
                .filter(services=self.service) \
447
                .order_by('start_datetime') \
448
                .select_related() \
449
                .prefetch_related(
450
                        'services',
451
                        'patient__service',
452
                        'act_set__actvalidationstate_set',
453
                        'exceptions', 'participants')
454
        events = [ e.today_occurrence(self.date) for e in events ] \
455
             + [ e.today_occurrence(self.date) for e in eventswithact ]
456
        for e in events:
457
            e.workers_ids = set(p.id for p in e.participants.all())
458

    
459
        events_workers = {}
460
        time_tables_workers = {}
461
        holidays_workers = {}
462
        context['workers_agenda'] = []
463
        context['workers'] = context['workers'].filter(services=self.service)
464
        for worker in context['workers']:
465
            time_tables_worker = [tt for tt in time_tables if tt.worker.id == worker.id]
466
            events_worker = [o for o in events if worker.id in o.workers_ids ]
467
            holidays_worker = [h for h in holidays if h.worker_id in (None, worker.id)]
468
            events_workers[worker.id] = events_worker
469
            time_tables_workers[worker.id] = time_tables_worker
470
            holidays_workers[worker.id] = holidays_worker
471
            daily_appointments = get_daily_appointments(context['date'], worker, self.service,
472
                        time_tables_worker, events_worker, holidays_worker)
473
            if all(map(lambda x: x.holiday, daily_appointments)):
474
                continue
475
            context['workers_agenda'].append({'worker': worker,
476
                    'appointments': daily_appointments})
477

    
478
        for worker_agenda in context.get('workers_agenda', []):
479
            patient_appointments = [x for x in worker_agenda['appointments'] if x.patient_record_id]
480
            worker_agenda['summary'] = {
481
              'rdv': len(patient_appointments),
482
              'presence': len([x for x in patient_appointments if x.act_absence is None]),
483
              'absence': len([x for x in patient_appointments if x.act_absence is not None]),
484
              'doubles': len([x for x in patient_appointments if x.act_type == 'ACT_DOUBLE']),
485
              'valides': len([x for x in patient_appointments if x.act_type == 'ACT_VALIDE']),
486
            }
487

    
488
        return context
489

    
490
class JoursNonVerrouillesView(TemplateView):
491
    template_name = 'agenda/days-not-locked.html'
492

    
493
    def get_context_data(self, **kwargs):
494
        context = super(JoursNonVerrouillesView, self).get_context_data(**kwargs)
495
        acts = Act.objects.filter(is_billed=False,
496
            patient__service=self.service).order_by('date')
497
        days = set(acts.values_list('date', flat=True))
498
        if days:
499
            max_day, min_day = max(days), min(days)
500
            today = datetime.datetime.today().date()
501
            if max_day > today:
502
                max_day = today
503
            days &= set(get_days_with_acts_not_locked(min_day, max_day, self.service))
504
        context['days_not_locked'] = sorted(days)
505
        return context
506

    
507
class RessourcesView(TemplateView):
508

    
509
    template_name = 'agenda/ressources.html'
510
    cookies_to_clear = []
511

    
512
    def get_context_data(self, **kwargs):
513
        context = super(RessourcesView, self).get_context_data(**kwargs)
514

    
515
        plain_events = Event.objects.for_today(self.date) \
516
                .order_by('start_datetime').select_subclasses()
517
        events = [ e.today_occurrence(self.date) for e in plain_events ]
518

    
519
        context['ressources_types'] = []
520
        context['ressources_agenda'] = []
521
        context['disponibility'] = {}
522
        ressources = []
523
        data = {'type': Room._meta.verbose_name_plural, 'ressources': Room.objects.all() }
524
        context['ressources_types'].append(data)
525
        ressources.extend(data['ressources'])
526

    
527
        events_ressources = {}
528
        for ressource in ressources:
529
            events_ressource = [e for e in events if ressource == e.room]
530
            events_ressources[ressource.id] = events_ressource
531
            context['ressources_agenda'].append({'ressource': ressource,
532
                    'appointments': get_daily_usage(context['date'], ressource,
533
                        self.service, events_ressource)})
534

    
535
        return context
536

    
537
class AjaxWorkerTabView(TemplateView):
538

    
539
    template_name = 'agenda/ajax-worker-tab.html'
540
    cookies_to_clear = []
541

    
542
    def get_context_data(self, worker_id, **kwargs):
543
        context = super(AjaxWorkerTabView, self).get_context_data(**kwargs)
544
        worker = Worker.objects.get(id=worker_id)
545

    
546
        time_tables_worker = TimeTable.objects.select_related('worker'). \
547
                filter(services=self.service, worker=worker) \
548
                .for_today(self.date) \
549
                .order_by('start_date') \
550
                .select_related()
551
        holidays_worker = Holiday.objects.for_worker(worker) \
552
                .for_period(self.date, self.date) \
553
                .order_by('start_date') \
554
                .select_related()
555
        events = Event.objects.for_today(self.date) \
556
                .exclude(event_type_id=1) \
557
                .filter(participants=worker) \
558
                .order_by('start_datetime') \
559
                .select_related() \
560
                .prefetch_related('services',
561
                        'exceptions',
562
                        'participants')
563
        eventswithact = EventWithAct.objects.for_today(self.date) \
564
                .filter(participants=worker) \
565
                .order_by('start_datetime') \
566
                .select_related() \
567
                .prefetch_related('patient__addresses',
568
                        'patient__addresses__patientcontact_set',
569
                        'services',
570
                        'patient__service',
571
                        'act_set__actvalidationstate_set',
572
                        'exceptions', 'participants')
573
        events = [ e.today_occurrence(self.date) for e in events ] \
574
             + [ e.today_occurrence(self.date) for e in eventswithact ]
575

    
576
        context['worker_agenda'] = {'worker': worker,
577
                    'appointments': get_daily_appointments(context['date'], worker, self.service,
578
                        time_tables_worker, events, holidays_worker)}
579

    
580
        if settings.RTF_TEMPLATES_DIRECTORY:
581
            context['mail'] = True
582
        return context
583

    
584
class AjaxWorkerDisponibilityColumnView(TemplateView):
585

    
586
    template_name = 'agenda/ajax-worker-disponibility-column.html'
587
    cookies_to_clear = []
588

    
589
    def get_context_data(self, worker_id, **kwargs):
590
        context = super(AjaxWorkerDisponibilityColumnView, self).get_context_data(**kwargs)
591
        worker = Worker.objects.get(pk=worker_id)
592

    
593
        time_tables_worker = TimeTable.objects.select_related('worker'). \
594
                filter(services=self.service, worker=worker). \
595
                for_today(self.date). \
596
                order_by('start_date')
597
        holidays_worker = Holiday.objects.for_worker(worker). \
598
                for_period(self.date, self.date). \
599
                order_by('start_date')
600
        events = Event.objects.for_today(self.date) \
601
                .exclude(event_type_id=1) \
602
                .filter(participants=worker) \
603
                .order_by('start_datetime') \
604
                .select_related() \
605
                .prefetch_related('participants', 'exceptions')
606
        eventswithact = EventWithAct.objects.for_today(self.date) \
607
                .filter(participants=worker) \
608
                .order_by('start_datetime') \
609
                .select_related() \
610
                .prefetch_related('participants', 'exceptions',
611
                        'act_set__actvalidationstate_set')
612

    
613
        events = list(events) + list(eventswithact)
614
        events = [ e.today_occurrence(self.date) for e in events ]
615
        time_tables_workers = {worker.id: time_tables_worker}
616
        events_workers = {worker.id: events}
617
        holidays_workers = {worker.id: holidays_worker}
618

    
619
        context['initials'] = worker.initials
620
        context['worker_id'] = worker.id
621
        context['disponibility'] = Event.objects.daily_disponibilities(self.date,
622
                events_workers, [worker], time_tables_workers, holidays_workers)
623
        return context
624

    
625

    
626
class PeriodicEventsView(cbv.ListView):
627
    model = EventWithAct
628
    template_name = 'agenda/periodic-events.html'
629
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
630

    
631
    def dispatch(self, request, *args, **kwargs):
632
        if 'worker_id' in kwargs:
633
            self.worker = get_object_or_404(Worker, id=kwargs['worker_id'])
634
        else:
635
            self.worker = None
636
        return super(PeriodicEventsView, self).dispatch(request, *args, **kwargs)
637

    
638
    def get_form(self):
639
        kwargs = {
640
                'initial': {
641
                    'start_date': self.date,
642
                }
643
        }
644
        if self.request.GET:
645
            kwargs['data'] = self.request.GET
646
        self.form = PeriodicEventsSearchForm(prefix='periodic-events-search-form', **kwargs)
647
        return self.form
648

    
649
    def get_queryset(self):
650
        qs1 = Event.objects.exclude(event_type_id=1)
651
        qs2 = EventWithAct.objects.all()
652
        form = self.get_form()
653
        if not self.request.GET:
654
            return ()
655
        qs1 = self.filter_queryset(form, qs1)
656
        qs2 = self.filter_queryset(form, qs2)
657
        if form.is_valid():
658
            patient = form.cleaned_data.get('patient')
659
            if patient is not None:
660
                qs1 = qs1.none()
661
                qs2 = qs2.filter(patient=patient)
662
            worker = form.cleaned_data.get('worker')
663
            if worker is not None:
664
                qs1 = qs1.filter(participants=worker)
665
                qs2 = qs2.filter(participants=worker)
666
        return sorted(chain(qs1, qs2),
667
                key=lambda x: (x.start_datetime, x.recurrence_end_date or datetime.date(9999,12,31)))
668

    
669
    def filter_queryset(self, form, qs):
670
        if self.worker is not None:
671
            qs = qs.filter(participants=self.worker)
672
        start_date = datetime.date.today()
673
        end_date = start_date+datetime.timedelta(days=90)
674
        if form.is_valid():
675
            if form.cleaned_data.get('start_date'):
676
                start_date = form.cleaned_data['start_date']
677
            if form.cleaned_data.get('end_date'):
678
                end_date = form.cleaned_data['end_date']
679
            else:
680
                end_date = start_date+datetime.timedelta(days=90)
681
            if len(form.cleaned_data.get('event_type')) != 2:
682
                if '0' in form.cleaned_data.get('event_type'):
683
                    qs = qs.filter(event_type_id=1)
684
                else:
685
                    qs = qs.exclude(event_type_id=1)
686
            if form.cleaned_data.get('no_end_date'):
687
                qs = qs.filter(recurrence_end_date__isnull=True)
688
        qs = qs.filter(services=self.service)
689
        qs = qs.filter(recurrence_periodicity__isnull=False)
690
        qs = qs.filter(start_datetime__lt=end_date)
691
        qs = qs.filter(Q(recurrence_end_date__isnull=True)
692
                | Q(recurrence_end_date__gte=start_date))
693
        qs = qs.order_by('start_datetime', 'recurrence_end_date')
694
        qs = qs.select_related()
695
        qs = qs.prefetch_related('participants', 'services')
696
        return qs
697

    
698
    def get_context_data(self, **kwargs):
699
        ctx = super(PeriodicEventsView, self).get_context_data(**kwargs)
700
        ctx['search_form'] = self.form
701
        ctx['worker'] = self.worker
702
        return ctx
(10-10/10)