Project

General

Profile

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

calebasse / calebasse / agenda / views.py @ b5f052b7

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

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

    
24
from forms import (NewAppointmentForm, NewEventForm,
25
        UpdateAppointmentForm, UpdateEventForm, PeriodicEventsSearchForm)
26

    
27

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

    
33

    
34
class AgendaHomepageView(TemplateView):
35
    template_name = 'agenda/index.html'
36

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

    
51
    def get_context_data(self, **kwargs):
52
        context = super(AgendaHomepageView, self).get_context_data(**kwargs)
53

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

    
67
        return context
68

    
69

    
70
class AgendaServiceActivityView(TemplateView):
71
    template_name = 'agenda/service-activity.html'
72

    
73
    def get_context_data(self, **kwargs):
74
        context = super(AgendaServiceActivityView, self).get_context_data(**kwargs)
75

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

    
122

    
123
class NewAppointmentView(cbv.ReturnToObjectMixin, cbv.ServiceFormMixin, CreateView):
124
    model = EventWithAct
125
    form_class = NewAppointmentForm
126
    template_name = 'agenda/new-appointment.html'
127
    success_url = '..'
128

    
129
    def get_initial(self):
130
        initial = super(NewAppointmentView, self).get_initial()
131
        initial['start_datetime'] = self.date
132
        initial['date'] = self.date
133
        initial['participants'] = self.request.GET.getlist('participants')
134
        initial['time'] = self.request.GET.get('time')
135
        initial['room'] = self.request.GET.get('room')
136
        return initial
137

    
138
    def get_form_kwargs(self):
139
        kwargs = super(NewAppointmentView, self).get_form_kwargs()
140
        kwargs['service'] = self.service
141
        return kwargs
142

    
143
    def form_valid(self, form):
144
        messages.add_message(self.request, messages.INFO, u'Rendez-vous enregistré avec succès.')
145
        return super(NewAppointmentView, self).form_valid(form)
146

    
147

    
148
class TodayOccurrenceMixin(object):
149
    def get_object(self, queryset=None):
150
        o = super(TodayOccurrenceMixin, self).get_object(queryset)
151
        return o.today_occurrence(self.date)
152

    
153

    
154
class BaseAppointmentView(UpdateView):
155
    model = EventWithAct
156
    form_class = UpdateAppointmentForm
157
    template_name = 'agenda/update-rdv.html'
158
    success_url = '..'
159

    
160
    def get_initial(self):
161
        initial = super(BaseAppointmentView, self).get_initial()
162
        initial['start_datetime'] = self.date
163
        initial['date'] = self.object.start_datetime.date()
164
        initial['time'] = self.object.start_datetime.time()
165
        time = self.object.end_datetime - self.object.start_datetime
166
        if time:
167
            time = time.seconds / 60
168
        else:
169
            time = 0
170
        initial['duration'] = time
171
        initial['participants'] = self.object.participants.values_list('id', flat=True)
172
        return initial
173

    
174
    def get_form_kwargs(self):
175
        kwargs = super(BaseAppointmentView, self).get_form_kwargs()
176
        kwargs['service'] = self.service
177
        return kwargs
178

    
179

    
180
class UpdateAppointmentView(TodayOccurrenceMixin, BaseAppointmentView):
181
    pass
182

    
183

    
184
class UpdatePeriodicAppointmentView(BaseAppointmentView):
185
    form_class = NewAppointmentForm
186
    template_name = 'agenda/new-appointment.html'
187

    
188

    
189
class NewEventView(CreateView):
190
    model = Event
191
    form_class = NewEventForm
192
    template_name = 'agenda/new-event.html'
193
    success_url = '..'
194

    
195
    def get_initial(self):
196
        initial = super(NewEventView, self).get_initial()
197
        initial['start_datetime'] = self.date
198
        initial['date'] = self.date
199
        initial['participants'] = self.request.GET.getlist('participants')
200
        initial['time'] = self.request.GET.get('time')
201
        initial['event_type'] = 2
202
        initial['room'] = self.request.GET.get('room')
203
        return initial
204

    
205
    def get_form_kwargs(self):
206
        kwargs = super(NewEventView, self).get_form_kwargs()
207
        kwargs['service'] = self.service
208
        return kwargs
209

    
210
    def form_valid(self, form):
211
        messages.add_message(self.request, messages.INFO, u'Evénement enregistré avec succès.')
212
        return super(NewEventView, self).form_valid(form)
213

    
214

    
215
class BaseEventView(UpdateView):
216
    model = Event
217
    form_class = UpdateEventForm
218
    template_name = 'agenda/update-event.html'
219
    success_url = '..'
220

    
221
    def get_initial(self):
222
        initial = super(BaseEventView, self).get_initial()
223
        initial['start_datetime'] = self.date
224
        initial['date'] = self.object.start_datetime.date()
225
        initial['time'] = self.object.start_datetime.time()
226
        time = self.object.end_datetime - self.object.start_datetime
227
        if time:
228
            time = time.seconds / 60
229
        else:
230
            time = 0
231
        initial['duration'] = time
232
        initial['participants'] = self.object.participants.values_list('id', flat=True)
233
        return initial
234

    
235
    def get_form_kwargs(self):
236
        kwargs = super(BaseEventView, self).get_form_kwargs()
237
        kwargs['service'] = self.service
238
        return kwargs
239

    
240

    
241
class UpdateEventView(TodayOccurrenceMixin, BaseEventView):
242
    pass
243

    
244

    
245
class UpdatePeriodicEventView(BaseEventView):
246
    form_class = NewEventForm
247
    template_name = 'agenda/new-event.html'
248

    
249

    
250
class DeleteOccurrenceView(TodayOccurrenceMixin, cbv.DeleteView):
251
    model = Event
252
    success_url = '..'
253

    
254
    def delete(self, request, *args, **kwargs):
255
        super(DeleteOccurrenceView, self).delete(request, *args, **kwargs)
256
        return HttpResponse(status=204)
257

    
258
class DeleteEventView(cbv.DeleteView):
259
    model = Event
260
    success_url = '..'
261

    
262
    def delete(self, request, *args, **kwargs):
263
        super(DeleteEventView, self).delete(request, *args, **kwargs)
264
        return HttpResponse(status=204)
265

    
266
class AgendaServiceActValidationView(TemplateView):
267
    template_name = 'agenda/act-validation.html'
268

    
269
    def acts_of_the_day(self):
270
        acts = list(Act.objects \
271
                .filter(date=self.date, patient__service=self.service) \
272
                .select_related() \
273
                .prefetch_related('doctors',
274
                        'patient__patientcontact',
275
                        'actvalidationstate_set__previous_state') \
276
                .order_by('time'))
277
        event_ids = [ a.parent_event_id for a in acts if a.parent_event_id ]
278
        events = EventWithAct.objects.for_today(self.date) \
279
                .filter(patient__service=self.service) \
280
                .exclude(id__in=event_ids)
281
        events = [ event.today_occurrence(self.date) for event in events ]
282
        acts += [ event.act for event in events if event ]
283
        return sorted(acts, key=lambda a: (a.time or datetime.time.min, a.id))
284

    
285
    def post(self, request, *args, **kwargs):
286
        if 'unlock-all' in request.POST:
287
            #TODO: check that the user is authorized
288
            unlock_all_acts_of_the_day(self.date, self.service)
289
            ValidationMessage(validation_date=self.date,
290
                who=request.user, what='Déverrouillage',
291
                service=self.service).save()
292
        else:
293
            acte_id = request.POST.get('acte-id')
294
            try:
295
                act = Act.objects.get(id=acte_id)
296
                if 'lock' in request.POST or 'unlock' in request.POST:
297
                    #TODO: check that the user is authorized
298
                    act.validation_locked = 'lock' in request.POST
299
                    act.save()
300
                else:
301
                    state_name = request.POST.get('act_state')
302
                    act.set_state(state_name, request.user)
303
            except Act.DoesNotExist:
304
                pass
305
            return HttpResponseRedirect('#acte-frame-'+acte_id)
306
        return HttpResponseRedirect('')
307

    
308
    def get_context_data(self, **kwargs):
309
        context = super(AgendaServiceActValidationView, self).get_context_data(**kwargs)
310
        authorized_lock = True # is_authorized_for_locking(get_request().user)
311
        validation_msg = ValidationMessage.objects.\
312
            filter(validation_date=self.date, service=self.service).\
313
            order_by('-when')[:3]
314
        acts_of_the_day = self.acts_of_the_day()
315
        actes = list()
316
        for act in acts_of_the_day:
317
            if not act.id:
318
                act.save()
319
            state = act.get_state()
320
            display_name = None
321
            if state :
322
                display_name = VALIDATION_STATES[state.state_name]
323
                if not state.previous_state_id and state.state_name == 'NON_VALIDE':
324
                    state = None
325
            actes.append((act, state, display_name))
326
        validation_states = dict(VALIDATION_STATES)
327
        if self.service.name != 'CMPP' and \
328
                'ACT_DOUBLE' in validation_states:
329
            validation_states.pop('ACT_DOUBLE')
330
        vs = [('VALIDE', 'Présent')]
331
        validation_states.pop('VALIDE')
332
        validation_states.pop('ACT_LOST')
333
        validation_states = vs + sorted(validation_states.items(), key=lambda tup: tup[0])
334
        context['validation_states'] = validation_states
335
        context['actes'] = actes
336
        context['validation_msg'] = validation_msg
337
        context['authorized_lock'] = authorized_lock
338
        return context
339

    
340

    
341
class AutomatedValidationView(TemplateView):
342
    template_name = 'agenda/automated-validation.html'
343

    
344
    def post(self, request, *args, **kwargs):
345
        automated_validation(self.date, self.service,
346
            request.user)
347
        ValidationMessage(validation_date=self.date,
348
            who=request.user, what='Validation automatique',
349
            service=self.service).save()
350
        return HttpResponseRedirect('..')
351

    
352
    def get_context_data(self, **kwargs):
353
        context = super(AutomatedValidationView, self).get_context_data(**kwargs)
354
        request = self.request
355
        (nb_acts_total, nb_acts_validated, nb_acts_double,
356
        nb_acts_abs_non_exc, nb_acts_abs_exc, nb_acts_abs_inter, nb_acts_annul_nous,
357
        nb_acts_annul_famille, nb_acts_reporte, nb_acts_abs_ess_pps,
358
        nb_acts_enf_hosp, nb_acts_losts) = \
359
            automated_validation(self.date, self.service,
360
                request.user, commit = False)
361

    
362
        nb_acts_not_validated = nb_acts_double + \
363
            nb_acts_abs_non_exc + \
364
            nb_acts_abs_exc + \
365
            nb_acts_abs_inter + \
366
            nb_acts_annul_nous + \
367
            nb_acts_annul_famille + \
368
            nb_acts_reporte + \
369
            nb_acts_abs_ess_pps + \
370
            nb_acts_enf_hosp + \
371
            nb_acts_losts
372
        context.update({
373
            'nb_acts_total': nb_acts_total,
374
            'nb_acts_validated': nb_acts_validated,
375
            'nb_acts_not_validated': nb_acts_not_validated,
376
            'nb_acts_double': nb_acts_double,
377
            'nb_acts_abs_non_exc': nb_acts_abs_non_exc,
378
            'nb_acts_abs_exc': nb_acts_abs_exc,
379
            'nb_acts_abs_inter': nb_acts_abs_inter,
380
            'nb_acts_annul_nous': nb_acts_annul_nous,
381
            'nb_acts_annul_famille': nb_acts_annul_famille,
382
            'nb_acts_reporte': nb_acts_reporte,
383
            'nb_acts_abs_ess_pps': nb_acts_abs_ess_pps,
384
            'nb_acts_enf_hosp': nb_acts_enf_hosp,
385
            'nb_acts_losts': nb_acts_losts})
386
        return context
387

    
388
class UnlockAllView(CreateView):
389
    pass
390

    
391

    
392
class AgendasTherapeutesView(AgendaHomepageView):
393
    template_name = 'agenda/agendas-therapeutes.html'
394

    
395
    def get_context_data(self, **kwargs):
396
        context = super(AgendasTherapeutesView, self).get_context_data(**kwargs)
397

    
398
        time_tables = TimeTable.objects.select_related('worker'). \
399
                filter(services=self.service). \
400
                for_today(self.date). \
401
                order_by('start_date')
402
        holidays = Holiday.objects.select_related('worker') \
403
                .for_period(self.date, self.date) \
404
                .order_by('start_date') \
405
                .select_related()
406
        events = Event.objects.for_today(self.date) \
407
                .exclude(event_type_id=1) \
408
                .filter(services=self.service) \
409
                .order_by('start_datetime') \
410
                .select_related() \
411
                .prefetch_related('services',
412
                        'exceptions',
413
                        'participants')
414
        eventswithact = EventWithAct.objects.for_today(self.date) \
415
                .filter(services=self.service) \
416
                .order_by('start_datetime') \
417
                .select_related() \
418
                .prefetch_related(
419
                        'services',
420
                        'patient__service',
421
                        'act_set__actvalidationstate_set',
422
                        'exceptions', 'participants')
423
        events = [ e.today_occurrence(self.date) for e in events ] \
424
             + [ e.today_occurrence(self.date) for e in eventswithact ]
425
        for e in events:
426
            e.workers_ids = set(p.id for p in e.participants.all())
427

    
428
        events_workers = {}
429
        time_tables_workers = {}
430
        holidays_workers = {}
431
        context['workers_agenda'] = []
432
        context['workers'] = context['workers'].filter(services=self.service)
433
        for worker in context['workers']:
434
            time_tables_worker = [tt for tt in time_tables if tt.worker.id == worker.id]
435
            events_worker = [o for o in events if worker.id in o.workers_ids ]
436
            holidays_worker = [h for h in holidays if h.worker_id in (None, worker.id)]
437
            events_workers[worker.id] = events_worker
438
            time_tables_workers[worker.id] = time_tables_worker
439
            holidays_workers[worker.id] = holidays_worker
440
            daily_appointments = get_daily_appointments(context['date'], worker, self.service,
441
                        time_tables_worker, events_worker, holidays_worker)
442
            if all(map(lambda x: x.holiday, daily_appointments)):
443
                continue
444
            context['workers_agenda'].append({'worker': worker,
445
                    'appointments': daily_appointments})
446

    
447
        for worker_agenda in context.get('workers_agenda', []):
448
            patient_appointments = [x for x in worker_agenda['appointments'] if x.patient_record_id]
449
            worker_agenda['summary'] = {
450
              'rdv': len(patient_appointments),
451
              'presence': len([x for x in patient_appointments if x.act_absence is None]),
452
              'absence': len([x for x in patient_appointments if x.act_absence is not None]),
453
              'doubles': len([x for x in patient_appointments if x.act_type == 'ACT_DOUBLE']),
454
              'valides': len([x for x in patient_appointments if x.act_type == 'ACT_VALIDE']),
455
            }
456

    
457
        return context
458

    
459
class JoursNonVerrouillesView(TemplateView):
460
    template_name = 'agenda/days-not-locked.html'
461

    
462
    def get_context_data(self, **kwargs):
463
        context = super(JoursNonVerrouillesView, self).get_context_data(**kwargs)
464
        acts = Act.objects.filter(is_billed=False,
465
            patient__service=self.service).order_by('date')
466
        days = set(acts.values_list('date', flat=True))
467
        if days:
468
            max_day, min_day = max(days), min(days)
469
            today = datetime.datetime.today().date()
470
            if max_day > today:
471
                max_day = today
472
            days &= set(get_days_with_acts_not_locked(min_day, max_day, self.service))
473
        context['days_not_locked'] = sorted(days)
474
        return context
475

    
476
class RessourcesView(TemplateView):
477

    
478
    template_name = 'agenda/ressources.html'
479

    
480
    def get_context_data(self, **kwargs):
481
        context = super(RessourcesView, self).get_context_data(**kwargs)
482

    
483
        plain_events = Event.objects.for_today(self.date) \
484
                .order_by('start_datetime').select_subclasses()
485
        events = [ e.today_occurrence(self.date) for e in plain_events ]
486

    
487
        context['ressources_types'] = []
488
        context['ressources_agenda'] = []
489
        context['disponibility'] = {}
490
        ressources = []
491
        data = {'type': Room._meta.verbose_name_plural, 'ressources': Room.objects.all() }
492
        context['ressources_types'].append(data)
493
        ressources.extend(data['ressources'])
494

    
495
        events_ressources = {}
496
        for ressource in ressources:
497
            events_ressource = [e for e in events if ressource == e.room]
498
            events_ressources[ressource.id] = events_ressource
499
            context['ressources_agenda'].append({'ressource': ressource,
500
                    'appointments': get_daily_usage(context['date'], ressource,
501
                        self.service, events_ressource)})
502

    
503
        return context
504

    
505
class AjaxWorkerTabView(TemplateView):
506

    
507
    template_name = 'agenda/ajax-worker-tab.html'
508

    
509
    def get_context_data(self, worker_id, **kwargs):
510
        context = super(AjaxWorkerTabView, self).get_context_data(**kwargs)
511
        worker = Worker.objects.get(id=worker_id)
512

    
513
        time_tables_worker = TimeTable.objects.select_related('worker'). \
514
                filter(services=self.service, worker=worker) \
515
                .for_today(self.date) \
516
                .order_by('start_date') \
517
                .select_related()
518
        holidays_worker = Holiday.objects.for_worker(worker) \
519
                .for_period(self.date, self.date) \
520
                .order_by('start_date') \
521
                .select_related()
522
        events = Event.objects.for_today(self.date) \
523
                .exclude(event_type_id=1) \
524
                .filter(participants=worker) \
525
                .order_by('start_datetime') \
526
                .select_related() \
527
                .prefetch_related('services',
528
                        'exceptions',
529
                        'participants')
530
        eventswithact = EventWithAct.objects.for_today(self.date) \
531
                .filter(participants=worker) \
532
                .order_by('start_datetime') \
533
                .select_related() \
534
                .prefetch_related('patient__addresses',
535
                        'patient__addresses__patientcontact_set',
536
                        'services',
537
                        'patient__service',
538
                        'act_set__actvalidationstate_set',
539
                        'exceptions', 'participants')
540
        events = [ e.today_occurrence(self.date) for e in events ] \
541
             + [ e.today_occurrence(self.date) for e in eventswithact ]
542

    
543
        context['worker_agenda'] = {'worker': worker,
544
                    'appointments': get_daily_appointments(context['date'], worker, self.service,
545
                        time_tables_worker, events, holidays_worker)}
546
        return context
547

    
548
class AjaxWorkerDisponibilityColumnView(TemplateView):
549

    
550
    template_name = 'agenda/ajax-worker-disponibility-column.html'
551

    
552
    def get_context_data(self, worker_id, **kwargs):
553
        context = super(AjaxWorkerDisponibilityColumnView, self).get_context_data(**kwargs)
554
        worker = Worker.objects.get(pk=worker_id)
555

    
556
        time_tables_worker = TimeTable.objects.select_related('worker'). \
557
                filter(services=self.service, worker=worker). \
558
                for_today(self.date). \
559
                order_by('start_date')
560
        holidays_worker = Holiday.objects.for_worker(worker). \
561
                for_period(self.date, self.date). \
562
                order_by('start_date')
563
        events = Event.objects.for_today(self.date) \
564
                .exclude(event_type_id=1) \
565
                .filter(participants=worker) \
566
                .order_by('start_datetime') \
567
                .select_related() \
568
                .prefetch_related('participants', 'exceptions')
569
        eventswithact = EventWithAct.objects.for_today(self.date) \
570
                .filter(participants=worker) \
571
                .order_by('start_datetime') \
572
                .select_related() \
573
                .prefetch_related('participants', 'exceptions',
574
                        'act_set__actvalidationstate_set')
575

    
576
        events = list(events) + list(eventswithact)
577
        events = [ e.today_occurrence(self.date) for e in events ]
578
        time_tables_workers = {worker.id: time_tables_worker}
579
        events_workers = {worker.id: events}
580
        holidays_workers = {worker.id: holidays_worker}
581

    
582
        context['initials'] = worker.get_initials()
583
        context['worker_id'] = worker.id
584
        context['disponibility'] = Event.objects.daily_disponibilities(self.date,
585
                events_workers, [worker], time_tables_workers, holidays_workers)
586
        return context
587

    
588

    
589
class PeriodicEventsView(cbv.ListView):
590
    model = EventWithAct
591
    template_name = 'agenda/periodic-events.html'
592

    
593
    def dispatch(self, request, *args, **kwargs):
594
        if 'worker_id' in kwargs:
595
            self.worker = get_object_or_404(Worker, id=kwargs['worker_id'])
596
        else:
597
            self.worker = None
598
        return super(PeriodicEventsView, self).dispatch(request, *args, **kwargs)
599

    
600
    def get_form(self):
601
        kwargs = {
602
                'initial': {
603
                    'start_date': self.date,
604
                }
605
        }
606
        if self.request.GET:
607
            kwargs['data'] = self.request.GET
608
        self.form = PeriodicEventsSearchForm(**kwargs)
609
        return self.form
610

    
611
    def get_queryset(self):
612
        qs1 = Event.objects.exclude(event_type_id=1)
613
        qs2 = EventWithAct.objects.all()
614
        form = self.get_form()
615
        qs1 = self.filter_queryset(form, qs1)
616
        qs2 = self.filter_queryset(form, qs2)
617
        if form.is_valid():
618
            patient = form.cleaned_data.get('patient')
619
            if patient is not None:
620
                qs1 = qs1.none()
621
                qs2 = qs2.filter(patient=patient)
622
        return sorted(chain(qs1, qs2),
623
                key=lambda x: (x.start_datetime, x.recurrence_end_date or datetime.date(9999,12,31)))
624

    
625
    def filter_queryset(self, form, qs):
626
        if self.worker is not None:
627
            qs = qs.filter(participants=self.worker)
628
        start_date = datetime.date.today()
629
        end_date = start_date+datetime.timedelta(days=90)
630
        if form.is_valid():
631
            if form.cleaned_data.get('start_date'):
632
                start_date = form.cleaned_data['start_date']
633
            if form.cleaned_data.get('end_date'):
634
                end_date = form.cleaned_data['end_date']
635
            else:
636
                end_date = start_date+datetime.timedelta(days=90)
637
            if len(form.cleaned_data.get('event_type')) != 2:
638
                if '0' in form.cleaned_data.get('event_type'):
639
                    qs = qs.filter(event_type_id=1)
640
                else:
641
                    qs = qs.exclude(event_type_id=1)
642
            if form.cleaned_data.get('no_end_date'):
643
                qs = qs.filter(recurrence_end_date__isnull=True)
644
        qs = qs.filter(services=self.service)
645
        qs = qs.filter(recurrence_periodicity__isnull=False)
646
        qs = qs.filter(start_datetime__lt=end_date)
647
        qs = qs.filter(Q(recurrence_end_date__isnull=True)
648
                | Q(recurrence_end_date__gte=start_date))
649
        qs = qs.order_by('start_datetime', 'recurrence_end_date')
650
        qs = qs.select_related()
651
        qs = qs.prefetch_related('participants', 'services')
652
        return qs
653

    
654
    def get_context_data(self, **kwargs):
655
        ctx = super(PeriodicEventsView, self).get_context_data(**kwargs)
656
        ctx['search_form'] = self.form
657
        ctx['worker'] = self.worker
658
        return ctx
(10-10/10)