Project

General

Profile

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

calebasse / calebasse / agenda / views.py @ 9ca08421

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

    
3
import datetime
4
import logging
5
from itertools import chain
6

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

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

    
26
from calebasse.agenda.forms import (NewAppointmentForm, NewEventForm, UpdatePeriodicAppointmentForm,
27
        DisablePatientAppointmentForm, UpdateAppointmentForm, UpdatePeriodicEventForm, 
28
        UpdateEventForm, PeriodicEventsSearchForm)
29

    
30
logger = logging.getLogger(__name__)
31

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

    
37

    
38
class AgendaHomepageView(TemplateView):
39
    template_name = 'agenda/index.html'
40
    cookies_to_clear = []
41

    
42
    def post(self, request, *args, **kwargs):
43
        acte_id = request.POST.get('event-id')
44
        try:
45
            event = EventWithAct.objects.get(id=acte_id)
46
            event = event.today_occurrence(self.date)
47
            act = event.act
48
            if not act.validation_locked:
49
                state_name = request.POST.get('act_state')
50
                act.save()
51
                act.set_state(state_name, request.user)
52
        except Act.DoesNotExist:
53
            logger.warning('agenda homepage acte_id %d not found' % acte_id)
54
        return HttpResponseRedirect('#acte-frame-'+acte_id)
55

    
56
    def get_context_data(self, **kwargs):
57
        logger.info('AgendaHomepageView.get_context_data called')
58
        context = super(AgendaHomepageView, self).get_context_data(**kwargs)
59

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

    
73
        return context
74

    
75

    
76
class AgendaServiceActivityView(TemplateView, cbv.ServiceViewMixin):
77
    template_name = 'agenda/service-activity.html'
78
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
79

    
80
    def get_context_data(self, **kwargs):
81
        context = super(AgendaServiceActivityView, self).get_context_data(**kwargs)
82

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

    
130

    
131
class NewAppointmentView(cbv.ReturnToObjectMixin, cbv.ServiceFormMixin, CreateView):
132
    model = EventWithAct
133
    form_class = NewAppointmentForm
134
    template_name = 'agenda/new-appointment.html'
135
    success_msg = u'Rendez-vous enregistré avec succès.'
136
    cookies_to_clear = []
137

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

    
147
    def get_form_kwargs(self):
148
        kwargs = super(NewAppointmentView, self).get_form_kwargs()
149
        kwargs['service'] = self.service
150
        return kwargs
151

    
152
    def get_success_url(self):
153
        return self.request.META.get('HTTP_REFERER', '..')
154

    
155
    def form_valid(self, form):
156
        messages.add_message(self.request, messages.INFO, self.success_msg)
157
        return super(NewAppointmentView, self).form_valid(form)
158

    
159

    
160
class TodayOccurrenceMixin(object):
161
    def get_object(self, queryset=None):
162
        o = super(TodayOccurrenceMixin, self).get_object(queryset)
163
        return o.today_occurrence(self.date)
164

    
165

    
166
class BaseAppointmentView(UpdateView):
167
    model = EventWithAct
168
    form_class = UpdateAppointmentForm
169
    template_name = 'agenda/update-rdv.html'
170
    success_url = '..'
171
    cookies_to_clear = []
172

    
173
    def get_initial(self):
174
        initial = super(BaseAppointmentView, self).get_initial()
175
        initial['start_datetime'] = self.date
176
        initial['date'] = self.object.start_datetime.date()
177
        initial['time'] = self.object.start_datetime.time()
178
        time = self.object.end_datetime - self.object.start_datetime
179
        if time:
180
            time = time.seconds / 60
181
        else:
182
            time = 0
183
        initial['duration'] = time
184
        initial['participants'] = self.object.participants.values_list('id', flat=True)
185
        return initial
186

    
187
    def get_form_kwargs(self):
188
        kwargs = super(BaseAppointmentView, self).get_form_kwargs()
189
        kwargs['service'] = self.service
190
        return kwargs
191

    
192

    
193
class UpdateAppointmentView(TodayOccurrenceMixin, BaseAppointmentView):
194

    
195
    def get_form_class(self):
196
        if self.object.exception_to and not self.object.exception_to.canceled:
197
            return DisablePatientAppointmentForm
198
        else:
199
            return self.form_class
200

    
201

    
202
class UpdatePeriodicAppointmentView(BaseAppointmentView):
203
    form_class = UpdatePeriodicAppointmentForm
204
    template_name = 'agenda/new-appointment.html'
205

    
206

    
207
class NewEventView(CreateView):
208
    model = Event
209
    form_class = NewEventForm
210
    template_name = 'agenda/new-event.html'
211
    cookies_to_clear = []
212

    
213
    def get_initial(self):
214
        initial = super(NewEventView, self).get_initial()
215
        initial['start_datetime'] = self.date
216
        initial['date'] = self.date
217
        initial['participants'] = self.request.GET.getlist('participants')
218
        initial['time'] = self.request.GET.get('time')
219
        initial['event_type'] = 2
220
        initial['room'] = self.request.GET.get('room')
221
        if not initial.has_key('services'):
222
            initial['services'] = [self.service]
223
        return initial
224

    
225
    def get_form_kwargs(self):
226
        kwargs = super(NewEventView, self).get_form_kwargs()
227
        kwargs['service'] = self.service
228
        return kwargs
229

    
230
    def get_success_url(self):
231
        return self.request.META.get('HTTP_REFERER', '..')
232

    
233
    def form_valid(self, form):
234
        messages.add_message(self.request, messages.INFO, u'Evénement enregistré avec succès.')
235
        return super(NewEventView, self).form_valid(form)
236

    
237

    
238
class BaseEventView(UpdateView):
239
    model = Event
240
    form_class = UpdateEventForm
241
    template_name = 'agenda/update-event.html'
242
    success_url = '..'
243
    cookies_to_clear = []
244

    
245
    def get_initial(self):
246
        initial = super(BaseEventView, self).get_initial()
247
        initial['start_datetime'] = self.date
248
        initial['date'] = self.object.start_datetime.date()
249
        initial['time'] = self.object.start_datetime.time()
250
        time = self.object.end_datetime - self.object.start_datetime
251
        if time:
252
            time = time.seconds / 60
253
        else:
254
            time = 0
255
        initial['duration'] = time
256
        initial['participants'] = self.object.participants.values_list('id', flat=True)
257
        return initial
258

    
259
    def get_form_kwargs(self):
260
        kwargs = super(BaseEventView, self).get_form_kwargs()
261
        kwargs['service'] = self.service
262
        return kwargs
263

    
264

    
265
class UpdateEventView(TodayOccurrenceMixin, BaseEventView):
266
    pass
267

    
268

    
269
class UpdatePeriodicEventView(BaseEventView):
270
    form_class = UpdatePeriodicEventForm
271
    template_name = 'agenda/new-event.html'
272

    
273

    
274
class DeleteOccurrenceView(TodayOccurrenceMixin, cbv.DeleteView):
275
    model = Event
276
    success_url = '..'
277
    cookies_to_clear = []
278

    
279
    def delete(self, request, *args, **kwargs):
280
        self.object = self.get_object()
281
        if self.object.event_type == 1 and self.object.act.id \
282
                and not self.object.act.is_billed:
283
            self.object.act.delete()
284
        self.object.delete()
285

    
286
        return HttpResponse(status=204)
287

    
288
class DeleteEventView(cbv.DeleteView):
289
    """
290
    TODO: Remove this class
291
    """
292
    model = Event
293
    success_url = '..'
294
    cookies_to_clear = []
295

    
296
    def delete(self, request, *args, **kwargs):
297
        super(DeleteEventView, self).delete(request, *args, **kwargs)
298
        return HttpResponse(status=204)
299

    
300
class AgendaServiceActValidationView(TemplateView):
301
    template_name = 'agenda/act-validation.html'
302
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
303

    
304
    def acts_of_the_day(self):
305
        acts = list(Act.objects \
306
                .filter(date=self.date, patient__service=self.service) \
307
                .select_related() \
308
                .prefetch_related('doctors',
309
                        'patient__patientcontact',
310
                        'actvalidationstate_set__previous_state') \
311
                .order_by('time'))
312
        event_ids = [ a.parent_event_id for a in acts if a.parent_event_id ]
313
        events = EventWithAct.objects.for_today(self.date) \
314
                .filter(patient__service=self.service) \
315
                .exclude(id__in=event_ids)
316
        events = [ event.today_occurrence(self.date) for event in events ]
317
        acts += [ event.act for event in events if event ]
318
        return sorted(acts, key=lambda a: (a.time or datetime.time.min, a.id))
319

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

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

    
378

    
379
class AutomatedValidationView(TemplateView):
380
    template_name = 'agenda/automated-validation.html'
381

    
382
    def post(self, request, *args, **kwargs):
383
        automated_validation(self.date, self.service,
384
            request.user)
385
        ValidationMessage(validation_date=self.date,
386
            who=request.user, what='Validation automatique',
387
            service=self.service).save()
388
        return HttpResponseRedirect('..')
389

    
390
    def get_context_data(self, **kwargs):
391
        context = super(AutomatedValidationView, self).get_context_data(**kwargs)
392
        request = self.request
393
        (nb_acts_total, nb_acts_validated, nb_acts_double,
394
        nb_acts_abs_non_exc, nb_acts_abs_exc, nb_acts_abs_inter, nb_acts_annul_nous,
395
        nb_acts_annul_famille, nb_acts_reporte, nb_acts_abs_ess_pps,
396
        nb_acts_enf_hosp, nb_acts_losts) = \
397
            automated_validation(self.date, self.service,
398
                request.user, commit = False)
399

    
400
        nb_acts_not_validated = nb_acts_double + \
401
            nb_acts_abs_non_exc + \
402
            nb_acts_abs_exc + \
403
            nb_acts_abs_inter + \
404
            nb_acts_annul_nous + \
405
            nb_acts_annul_famille + \
406
            nb_acts_reporte + \
407
            nb_acts_abs_ess_pps + \
408
            nb_acts_enf_hosp + \
409
            nb_acts_losts
410
        context.update({
411
            'nb_acts_total': nb_acts_total,
412
            'nb_acts_validated': nb_acts_validated,
413
            'nb_acts_not_validated': nb_acts_not_validated,
414
            'nb_acts_double': nb_acts_double,
415
            'nb_acts_abs_non_exc': nb_acts_abs_non_exc,
416
            'nb_acts_abs_exc': nb_acts_abs_exc,
417
            'nb_acts_abs_inter': nb_acts_abs_inter,
418
            'nb_acts_annul_nous': nb_acts_annul_nous,
419
            'nb_acts_annul_famille': nb_acts_annul_famille,
420
            'nb_acts_reporte': nb_acts_reporte,
421
            'nb_acts_abs_ess_pps': nb_acts_abs_ess_pps,
422
            'nb_acts_enf_hosp': nb_acts_enf_hosp,
423
            'nb_acts_losts': nb_acts_losts})
424
        return context
425

    
426
class UnlockAllView(CreateView):
427
    pass
428

    
429

    
430
class AgendasTherapeutesView(AgendaHomepageView):
431
    template_name = 'agenda/agendas-therapeutes.html'
432
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
433

    
434
    def get_context_data(self, **kwargs):
435
        context = super(AgendasTherapeutesView, self).get_context_data(**kwargs)
436

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

    
467
        events_workers = {}
468
        time_tables_workers = {}
469
        holidays_workers = {}
470
        context['workers_agenda'] = []
471
        context['workers'] = context['workers'].filter(services=self.service)
472
        for worker in context['workers']:
473
            time_tables_worker = [tt for tt in time_tables if tt.worker.id == worker.id]
474
            events_worker = [o for o in events if worker.id in o.workers_ids ]
475
            holidays_worker = [h for h in holidays if h.worker_id in (None, worker.id)]
476
            events_workers[worker.id] = events_worker
477
            time_tables_workers[worker.id] = time_tables_worker
478
            holidays_workers[worker.id] = holidays_worker
479
            daily_appointments = get_daily_appointments(context['date'], worker, self.service,
480
                        time_tables_worker, events_worker, holidays_worker)
481
            if all(map(lambda x: x.holiday, daily_appointments)):
482
                continue
483
            context['workers_agenda'].append({'worker': worker,
484
                    'appointments': daily_appointments})
485

    
486
        for worker_agenda in context.get('workers_agenda', []):
487
            patient_appointments = [x for x in worker_agenda['appointments'] if x.patient_record_id]
488
            worker_agenda['summary'] = {
489
              'rdv': len(patient_appointments),
490
              'presence': len([x for x in patient_appointments if x.act_absence is None]),
491
              'absence': len([x for x in patient_appointments if x.act_absence is not None]),
492
              'doubles': len([x for x in patient_appointments if x.act_type == 'ACT_DOUBLE']),
493
              'valides': len([x for x in patient_appointments if x.act_type == 'ACT_VALIDE']),
494
            }
495

    
496
        return context
497

    
498
class JoursNonVerrouillesView(TemplateView):
499
    template_name = 'agenda/days-not-locked.html'
500

    
501
    def get_context_data(self, **kwargs):
502
        context = super(JoursNonVerrouillesView, self).get_context_data(**kwargs)
503
        acts = Act.objects.filter(is_billed=False,
504
            patient__service=self.service).order_by('date')
505
        days = set(acts.values_list('date', flat=True))
506
        if days:
507
            max_day, min_day = max(days), min(days)
508
            today = datetime.datetime.today().date()
509
            if max_day > today:
510
                max_day = today
511
            days &= set(get_days_with_acts_not_locked(min_day, max_day, self.service))
512
        context['days_not_locked'] = sorted(days)
513
        return context
514

    
515
class RessourcesView(TemplateView):
516

    
517
    template_name = 'agenda/ressources.html'
518
    cookies_to_clear = []
519

    
520
    def get_context_data(self, **kwargs):
521
        context = super(RessourcesView, self).get_context_data(**kwargs)
522

    
523
        plain_events = Event.objects.for_today(self.date) \
524
                .order_by('start_datetime').select_subclasses()
525
        events = [ e.today_occurrence(self.date) for e in plain_events ]
526

    
527
        context['ressources_types'] = []
528
        context['ressources_agenda'] = []
529
        context['disponibility'] = {}
530
        ressources = []
531
        data = {'type': Room._meta.verbose_name_plural, 'ressources': Room.objects.all() }
532
        context['ressources_types'].append(data)
533
        ressources.extend(data['ressources'])
534
        context['disponibility_start_times'] = range(8, 20)
535

    
536
        events_ressources = {}
537
        for ressource in ressources:
538
            events_ressource = [e for e in events if ressource == e.room]
539
            events_ressources[ressource.id] = events_ressource
540
            context['ressources_agenda'].append({'ressource': ressource,
541
                    'appointments': get_daily_usage(context['date'], ressource,
542
                        self.service, events_ressource)})
543

    
544
        return context
545

    
546
class AjaxWorkerTabView(TemplateView):
547

    
548
    template_name = 'agenda/ajax-worker-tab.html'
549
    cookies_to_clear = []
550

    
551
    def get_context_data(self, worker_id, **kwargs):
552
        context = super(AjaxWorkerTabView, self).get_context_data(**kwargs)
553
        worker = Worker.objects.get(id=worker_id)
554

    
555
        time_tables_worker = TimeTable.objects.select_related('worker'). \
556
                filter(services=self.service, worker=worker) \
557
                .for_today(self.date) \
558
                .order_by('start_date') \
559
                .select_related()
560
        holidays_worker = Holiday.objects.for_worker(worker) \
561
                .for_period(self.date, self.date) \
562
                .order_by('start_date') \
563
                .select_related()
564
        events = Event.objects.for_today(self.date) \
565
                .exclude(event_type_id=1) \
566
                .filter(participants=worker) \
567
                .order_by('start_datetime') \
568
                .select_related() \
569
                .prefetch_related('services',
570
                        'exceptions',
571
                        'participants')
572
        eventswithact = EventWithAct.objects.for_today(self.date) \
573
                .filter(participants=worker) \
574
                .order_by('start_datetime') \
575
                .select_related() \
576
                .prefetch_related('patient__addresses',
577
                        'patient__addresses__patientcontact_set',
578
                        'services',
579
                        'patient__service',
580
                        'act_set__actvalidationstate_set',
581
                        'exceptions', 'participants')
582
        events = [ e.today_occurrence(self.date) for e in events ] \
583
             + [ e.today_occurrence(self.date) for e in eventswithact ]
584

    
585
        context['worker_agenda'] = {'worker': worker,
586
                    'appointments': get_daily_appointments(context['date'], worker, self.service,
587
                        time_tables_worker, events, holidays_worker)}
588

    
589
        if settings.RTF_TEMPLATES_DIRECTORY:
590
            context['mail'] = True
591
        return context
592

    
593
class AjaxWorkerDisponibilityColumnView(TemplateView):
594

    
595
    template_name = 'agenda/ajax-ressource-disponibility-column.html'
596
    cookies_to_clear = []
597

    
598
    def get_context_data(self, worker_id, **kwargs):
599
        context = super(AjaxWorkerDisponibilityColumnView, self).get_context_data(**kwargs)
600
        worker = Worker.objects.get(pk=worker_id)
601

    
602
        time_tables_worker = TimeTable.objects.select_related('worker'). \
603
                filter(services=self.service, worker=worker). \
604
                for_today(self.date). \
605
                order_by('start_date')
606
        holidays_worker = Holiday.objects.for_worker(worker). \
607
                for_period(self.date, self.date). \
608
                order_by('start_date')
609
        events = Event.objects.for_today(self.date) \
610
                .exclude(event_type_id=1) \
611
                .filter(participants=worker) \
612
                .order_by('start_datetime') \
613
                .select_related() \
614
                .prefetch_related('participants', 'exceptions')
615
        eventswithact = EventWithAct.objects.for_today(self.date) \
616
                .filter(participants=worker) \
617
                .order_by('start_datetime') \
618
                .select_related() \
619
                .prefetch_related('participants', 'exceptions',
620
                        'act_set__actvalidationstate_set')
621

    
622
        events = list(events) + list(eventswithact)
623
        events = [ e.today_occurrence(self.date) for e in events ]
624
        time_tables_workers = {worker.id: time_tables_worker}
625
        events_workers = {worker.id: events}
626
        holidays_workers = {worker.id: holidays_worker}
627

    
628
        context['initials'] = worker.initials
629
        context['ressource_id'] = worker.id
630
        context['disponibility'] = Event.objects.daily_disponibilities(self.date,
631
                events_workers, [worker], time_tables_workers, holidays_workers)
632
        return context
633

    
634
class AjaxRessourceDisponibilityColumnView(AjaxWorkerDisponibilityColumnView):
635

    
636
    def get_context_data(self, ressource_id, **kwargs):
637
        context = {}
638
        ressource = Room.objects.get(pk = ressource_id)
639
        context = {'initials': ressource.name[:3], 'ressource_id': ressource.id}
640
        disponibility = dict()
641
        start_datetime = datetime.datetime(self.date.year,
642
                                           self.date.month,
643
                                           self.date.day, 8, 0)
644
        end_datetime = datetime.datetime(self.date.year, self.date.month,
645
                                         self.date.day, 8, 15)
646
        events = Event.objects.filter(room__id=ressource_id).today_occurrences(self.date)
647

    
648
        while (start_datetime.hour <= 19):
649
            if start_datetime.hour not in disponibility:
650
                disponibility[start_datetime.hour] = [[], [], [], []]
651
                quarter = 0
652
            dispo = 'free'
653

    
654
            if events:
655
                event = events[0]
656

    
657
                if event.start_datetime <= start_datetime and event.end_datetime >= end_datetime:
658
                    dispo = 'busy'
659

    
660
            disponibility[start_datetime.hour][quarter].append({'id': ressource_id, 'dispo': dispo})
661
            quarter += 1
662
            start_datetime += datetime.timedelta(minutes=15)
663
            end_datetime += datetime.timedelta(minutes=15)
664
        context['disponibility'] = disponibility
665
        return context
666

    
667

    
668
class PeriodicEventsView(cbv.ListView):
669
    model = EventWithAct
670
    template_name = 'agenda/periodic-events.html'
671
    cookies_to_clear = [('agenda-worker-tabs', ), ('agenda-ressource-tabs', )]
672

    
673
    def dispatch(self, request, *args, **kwargs):
674
        if 'worker_id' in kwargs:
675
            self.worker = get_object_or_404(Worker, id=kwargs['worker_id'])
676
        else:
677
            self.worker = None
678
        return super(PeriodicEventsView, self).dispatch(request, *args, **kwargs)
679

    
680
    def get_form(self):
681
        kwargs = {
682
                'initial': {
683
                    'start_date': self.date,
684
                }
685
        }
686
        if self.request.GET:
687
            kwargs['data'] = self.request.GET
688
        self.form = PeriodicEventsSearchForm(prefix='periodic-events-search-form', **kwargs)
689
        return self.form
690

    
691
    def get_queryset(self):
692
        qs1 = Event.objects.exclude(event_type_id=1)
693
        qs2 = EventWithAct.objects.all()
694
        form = self.get_form()
695
        if not self.request.GET:
696
            return ()
697
        qs1 = self.filter_queryset(form, qs1)
698
        qs2 = self.filter_queryset(form, qs2)
699
        if form.is_valid():
700
            patient = form.cleaned_data.get('patient')
701
            if patient is not None:
702
                qs1 = qs1.none()
703
                qs2 = qs2.filter(patient=patient)
704
            worker = form.cleaned_data.get('worker')
705
            if worker is not None:
706
                qs1 = qs1.filter(participants=worker)
707
                qs2 = qs2.filter(participants=worker)
708
        return sorted(chain(qs1, qs2),
709
                key=lambda x: (x.start_datetime, x.recurrence_end_date or datetime.date(9999,12,31)))
710

    
711
    def filter_queryset(self, form, qs):
712
        if self.worker is not None:
713
            qs = qs.filter(participants=self.worker)
714
        start_date = datetime.date.today()
715
        end_date = start_date+datetime.timedelta(days=90)
716
        if form.is_valid():
717
            if form.cleaned_data.get('start_date'):
718
                start_date = form.cleaned_data['start_date']
719
            if form.cleaned_data.get('end_date'):
720
                end_date = form.cleaned_data['end_date']
721
            else:
722
                end_date = start_date+datetime.timedelta(days=90)
723
            if len(form.cleaned_data.get('event_type')) != 2:
724
                if '0' in form.cleaned_data.get('event_type'):
725
                    qs = qs.filter(event_type_id=1)
726
                else:
727
                    qs = qs.exclude(event_type_id=1)
728
            if form.cleaned_data.get('no_end_date'):
729
                qs = qs.filter(recurrence_end_date__isnull=True)
730
        qs = qs.filter(canceled=False)
731
        qs = qs.filter(services=self.service)
732
        qs = qs.filter(recurrence_periodicity__isnull=False)
733
        qs = qs.filter(start_datetime__lt=end_date)
734
        qs = qs.filter(Q(recurrence_end_date__isnull=True)
735
                | Q(recurrence_end_date__gte=start_date))
736
        qs = qs.order_by('start_datetime', 'recurrence_end_date')
737
        qs = qs.select_related()
738
        qs = qs.prefetch_related('participants', 'services')
739
        return qs
740

    
741
    def get_context_data(self, **kwargs):
742
        ctx = super(PeriodicEventsView, self).get_context_data(**kwargs)
743
        ctx['search_form'] = self.form
744
        ctx['worker'] = self.worker
745
        return ctx
(10-10/10)