Project

General

Profile

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

calebasse / calebasse / dossiers / views.py @ 6e9b19bc

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

    
3
import os
4

    
5
from datetime import datetime, date
6

    
7
from django.conf import settings
8
from django.core.urlresolvers import reverse_lazy
9
from django.db import models
10
from django.http import HttpResponseRedirect, HttpResponse
11
from django.views.generic import View
12
from django.views.generic.edit import DeleteView, FormMixin
13
from django.contrib import messages
14
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
15

    
16
from calebasse import cbv
17
from calebasse.doc_templates import make_doc_from_template
18
from calebasse.dossiers import forms
19
from calebasse.agenda.models import Event, EventWithAct
20
from calebasse.actes.models import Act
21
from calebasse.agenda.appointments import Appointment
22
from calebasse.dossiers.models import (PatientRecord, PatientContact,
23
        PatientAddress, Status, FileState, create_patient, CmppHealthCareTreatment,
24
        CmppHealthCareDiagnostic, SessadHealthCareNotification, HealthCare)
25
from calebasse.dossiers.states import STATES_MAPPING, STATE_CHOICES_TYPE, STATES_BTN_MAPPER
26
from calebasse.ressources.models import (Service,
27
    SocialisationDuration, MDPHRequest, MDPHResponse)
28
from calebasse.facturation.list_acts import list_acts_for_billing_CMPP_2_per_patient
29

    
30
from calebasse.decorators import validator_only
31

    
32
def get_next_rdv(patient_record):
33
    Q = models.Q
34
    today = date.today()
35
    qs = EventWithAct.objects.filter(patient=patient_record) \
36
            .filter(exception_to__isnull=True, canceled=False) \
37
            .filter(Q(start_datetime__gte=today) \
38
            |  Q(exceptions__isnull=False) \
39
            | ( Q(recurrence_periodicity__isnull=False) \
40
            & (Q(recurrence_end_date__gte=today) \
41
            | Q(recurrence_end_date__isnull=True) \
42
            ))) \
43
            .distinct() \
44
            .select_related() \
45
            .prefetch_related('participants', 'exceptions__eventwithact')
46
    occurrences = []
47
    for event in qs:
48
        occurrences.extend(filter(lambda e: e.start_datetime.date() >= today, event.all_occurences(limit=180)))
49
    occurrences = sorted(occurrences, key=lambda e: e.start_datetime)
50
    if occurrences:
51
        return occurrences[0]
52
    else:
53
        return None
54

    
55
def get_last_rdv(patient_record):
56
    last_rdv = {}
57
    event = Event.objects.last_appointment(patient_record)
58
    if event:
59
        last_rdv['start_datetime'] = event.start_datetime
60
        last_rdv['participants'] = event.participants.all()
61
        last_rdv['act_type'] = event.eventwithact.act_type
62
        last_rdv['act_state'] = event.act.get_state()
63
        last_rdv['is_absent'] = event.is_absent()
64
    return last_rdv
65

    
66
class NewPatientRecordView(cbv.FormView, cbv.ServiceViewMixin):
67
    form_class = forms.NewPatientRecordForm
68
    template_name = 'dossiers/patientrecord_new.html'
69
    success_url = '..'
70
    patient = None
71

    
72
    def post(self, request, *args, **kwarg):
73
        self.user = request.user
74
        return super(NewPatientRecordView, self).post(request, *args, **kwarg)
75

    
76
    def form_valid(self, form):
77
        self.patient = create_patient(form.data['first_name'], form.data['last_name'], self.service,
78
                self.user, date_selected=datetime.strptime(form.data['date_selected'], "%d/%m/%Y"))
79
        return super(NewPatientRecordView, self).form_valid(form)
80

    
81
    def get_success_url(self):
82
        return '%s/view' % self.patient.id
83

    
84
new_patient_record = NewPatientRecordView.as_view()
85

    
86
class RecordPatientRecordIdMixing(object):
87
    def dispatch(self, request, *args, **kwargs):
88
        self.patientrecord_id = request.session['patientrecord_id'] = int(kwargs['patientrecord_id'])
89
        return super(RecordPatientRecordIdMixing, self).dispatch(request, *args, **kwargs)
90

    
91
    def get_form_kwargs(self):
92
        kwargs = super(RecordPatientRecordIdMixing, self).get_form_kwargs()
93
        kwargs['patient'] = PatientRecord.objects.get(id=self.patientrecord_id)
94
        return kwargs
95

    
96
class NewPatientContactView(RecordPatientRecordIdMixing, cbv.CreateView):
97
    model = PatientContact
98
    form_class = forms.PatientContactForm
99
    template_name = 'dossiers/patientcontact_new.html'
100
    success_url = '../view#tab=2'
101

    
102
new_patient_contact = NewPatientContactView.as_view()
103

    
104
class UpdatePatientContactView(RecordPatientRecordIdMixing, cbv.UpdateView):
105
    model = PatientContact
106
    form_class = forms.PatientContactForm
107
    template_name = 'dossiers/patientcontact_new.html'
108
    success_url = '../../view#tab=2'
109

    
110
update_patient_contact = UpdatePatientContactView.as_view()
111

    
112
class DeletePatientContactView(cbv.DeleteView):
113
    model = PatientContact
114
    form_class = forms.PatientContactForm
115
    template_name = 'dossiers/patientcontact_confirm_delete.html'
116
    success_url = '../../view#tab=2'
117

    
118
    def post(self, request, *args, **kwargs):
119
        try:
120
            patient = PatientRecord.objects.get(id=kwargs.get('pk'))
121
        except PatientRecord.DoesNotExist:
122
            return super(DeletePatientContactView, self).post(request, *args, **kwargs)
123
        # the contact is also a patient record; it shouldn't be deleted; just
124
        # altered to remove an address
125
        patient.addresses.remove(self.request.GET['address'])
126
        return HttpResponseRedirect(self.get_success_url())
127

    
128
delete_patient_contact = DeletePatientContactView.as_view()
129

    
130
class NewPatientAddressView(cbv.CreateView):
131
    model = PatientAddress
132
    form_class = forms.PatientAddressForm
133
    template_name = 'dossiers/patientaddress_new.html'
134
    success_url = '../view#tab=2'
135

    
136
    def get_success_url(self):
137
        return self.success_url
138

    
139
    def form_valid(self, form):
140
        patientaddress = form.save()
141
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
142
        patientrecord.addresses.add(patientaddress)
143
        messages.add_message(self.request, messages.INFO, u'Nouvelle adresse enregistrée avec succès.')
144
        return HttpResponseRedirect(self.get_success_url())
145

    
146
new_patient_address = NewPatientAddressView.as_view()
147

    
148
class UpdatePatientAddressView(cbv.UpdateView):
149
    model = PatientAddress
150
    form_class = forms.PatientAddressForm
151
    template_name = 'dossiers/patientaddress_new.html'
152
    success_url = '../../view#tab=2'
153

    
154
    def form_valid(self, form):
155
        messages.add_message(self.request, messages.INFO, u'Modification enregistrée avec succès.')
156
        return super(UpdatePatientAddressView, self).form_valid(form)
157

    
158
update_patient_address = UpdatePatientAddressView.as_view()
159

    
160
class DeletePatientAddressView(cbv.DeleteView):
161
    model = PatientAddress
162
    form_class = forms.PatientAddressForm
163
    template_name = 'dossiers/patientaddress_confirm_delete.html'
164
    success_url = '../../view#tab=2'
165

    
166
delete_patient_address = DeletePatientAddressView.as_view()
167

    
168

    
169
class NewHealthCareView(cbv.CreateView):
170

    
171
    def get_initial(self):
172
        initial = super(NewHealthCareView, self).get_initial()
173
        initial['author'] = self.request.user.id
174
        initial['patient'] = self.kwargs['patientrecord_id']
175
        return initial
176

    
177
new_healthcare_treatment = \
178
    NewHealthCareView.as_view(model=CmppHealthCareTreatment,
179
        template_name = 'dossiers/generic_form.html',
180
        success_url = '../view#tab=3',
181
        form_class=forms.CmppHealthCareTreatmentForm)
182
new_healthcare_diagnostic = \
183
    NewHealthCareView.as_view(model=CmppHealthCareDiagnostic,
184
        template_name = 'dossiers/generic_form.html',
185
        success_url = '../view#tab=3',
186
        form_class=forms.CmppHealthCareDiagnosticForm)
187
new_healthcare_notification = \
188
    NewHealthCareView.as_view(model=SessadHealthCareNotification,
189
        template_name = 'dossiers/generic_form.html',
190
        success_url = '../view#tab=3',
191
        form_class=forms.SessadHealthCareNotificationForm)
192
update_healthcare_treatment = \
193
    cbv.UpdateView.as_view(model=CmppHealthCareTreatment,
194
        template_name = 'dossiers/generic_form.html',
195
        success_url = '../../view#tab=3',
196
        form_class=forms.CmppHealthCareTreatmentForm)
197
update_healthcare_diagnostic = \
198
    cbv.UpdateView.as_view(model=CmppHealthCareDiagnostic,
199
        template_name = 'dossiers/generic_form.html',
200
        success_url = '../../view#tab=3',
201
        form_class=forms.CmppHealthCareDiagnosticForm)
202
update_healthcare_notification = \
203
    cbv.UpdateView.as_view(model=SessadHealthCareNotification,
204
        template_name = 'dossiers/generic_form.html',
205
        success_url = '../../view#tab=3',
206
        form_class=forms.SessadHealthCareNotificationForm)
207
delete_healthcare_treatment = \
208
    cbv.DeleteView.as_view(model=CmppHealthCareTreatment,
209
        template_name = 'dossiers/generic_confirm_delete.html',
210
        success_url = '../../view#tab=3')
211
delete_healthcare_diagnostic = \
212
    cbv.DeleteView.as_view(model=CmppHealthCareDiagnostic,
213
        template_name = 'dossiers/generic_confirm_delete.html',
214
        success_url = '../../view#tab=3')
215
delete_healthcare_notification = \
216
    cbv.DeleteView.as_view(model=SessadHealthCareNotification,
217
        template_name = 'dossiers/generic_confirm_delete.html',
218
        success_url = '../../view#tab=3')
219

    
220

    
221
class StateFormView(cbv.FormView):
222
    template_name = 'dossiers/state.html'
223
    form_class = forms.StateForm
224
    success_url = './view#tab=0'
225

    
226

    
227
    def post(self, request, *args, **kwarg):
228
        self.user = request.user
229
        return super(StateFormView, self).post(request, *args, **kwarg)
230

    
231
    def form_valid(self, form):
232
        service = Service.objects.get(id=form.data['service_id'])
233
        status = Status.objects.filter(services=service).filter(type=form.data['state_type'])
234
        patient = PatientRecord.objects.get(id=form.data['patient_id'])
235
        date_selected = datetime.strptime(form.data['date'], "%d/%m/%Y")
236
        patient.set_state(status[0], self.user, date_selected, form.data['comment'])
237
        return super(StateFormView, self).form_valid(form)
238

    
239
state_form = StateFormView.as_view()
240

    
241

    
242
class PatientRecordView(cbv.ServiceViewMixin, cbv.MultiUpdateView):
243
    model = PatientRecord
244
    forms_classes = {
245
            'general': forms.GeneralForm,
246
            'id': forms.CivilStatusForm,
247
            'physiology': forms.PhysiologyForm,
248
            'inscription': forms.InscriptionForm,
249
            'out': forms.OutForm,
250
            'family': forms.FamilyForm,
251
            'transport': forms.TransportFrom,
252
            'followup': forms.FollowUpForm,
253
            'policyholder': forms.PolicyHolderForm
254
            }
255
    template_name = 'dossiers/patientrecord_update.html'
256
    success_url = './view'
257

    
258
    def get_success_url(self):
259
        if self.request.POST.has_key('tab'):
260
            return self.success_url + '#tab=' + self.request.POST['tab']
261
        else:
262
            return self.success_url
263

    
264
    def get_context_data(self, **kwargs):
265
        ctx = super(PatientRecordView, self).get_context_data(**kwargs)
266
        ctx['initial_state'] = ctx['object'].get_initial_state()
267
        current_state = ctx['object'].get_current_state()
268
        if STATES_MAPPING.has_key(current_state.status.type):
269
            state = STATES_MAPPING[current_state.status.type]
270
        else:
271
            state = current_state.status.name
272
        ctx['current_state'] = current_state
273
        ctx['service_id'] = self.service.id
274
        ctx['states'] = FileState.objects.filter(patient=self.object) \
275
                .filter(status__services=self.service) \
276
                .order_by('-date_selected')
277
        ctx['next_rdvs'] = []
278
        Q = models.Q
279
        today = date.today()
280
        qs = EventWithAct.objects.filter(patient=ctx['object']) \
281
                .filter(exception_to__isnull=True, canceled=False) \
282
                .filter(Q(start_datetime__gte=today) \
283
                |  Q(exceptions__isnull=False) \
284
                | ( Q(recurrence_periodicity__isnull=False) \
285
                & (Q(recurrence_end_date__gte=today) \
286
                | Q(recurrence_end_date__isnull=True) \
287
                ))) \
288
                .distinct() \
289
                .select_related() \
290
                .prefetch_related('participants', 'exceptions__eventwithact', 'act_set__actvalidationstate_set')
291
        occurrences = []
292
        for event in qs:
293
            occurrences.extend(filter(lambda e: e.start_datetime.date() >= today, event.all_occurences(limit=180)))
294
        occurrences = sorted(occurrences, key=lambda e: e.start_datetime)
295
        for event in occurrences:
296
            state = None
297
            if event.act:
298
                state = event.act.get_state()
299
            if state and not state.previous_state and state.state_name == 'NON_VALIDE':
300
                state = None
301
            ctx['next_rdvs'].append((event, state))
302
        if ctx['next_rdvs']:
303
            ctx['next_rdv'] = ctx['next_rdvs'][0][0]
304
        ctx['last_rdvs'] = []
305
        for act in Act.objects.last_acts(ctx['object']).prefetch_related('doctors'):
306
            state = act.get_state()
307
            if state and not state.previous_state and state.state_name == 'NON_VALIDE':
308
                state = None
309
            ctx['last_rdvs'].append((act, state))
310
        ctx['last_rdv'] = get_last_rdv(ctx['object'])
311

    
312
        ctx['missing_policy'] = False
313
        if not self.object.policyholder or \
314
                not self.object.policyholder.health_center or \
315
                not self.object.policyholder.social_security_id:
316
            ctx['missing_policy'] = True
317

    
318
        ctx['status'] = []
319
        if ctx['object'].service.name == "CMPP":
320
            ctx['can_rediag'] = self.object.create_diag_healthcare(self.request.user)
321
            status = self.object.get_healthcare_status()
322
            highlight = False
323
            if status[0] == -1:
324
                status = 'Indéterminé.'
325
                highlight = True
326
            elif status[0] == 0:
327
                status = "Prise en charge de diagnostic en cours."
328
            elif status[0] == 1:
329
                status = 'Patient jamais pris en charge.'
330
            elif status[0] == 2:
331
                status = "Prise en charge de diagnostic complète, faire une demande de prise en charge de traitement."
332
                highlight = True
333
            elif status[0] == 3:
334
                if ctx['can_rediag']:
335
                    status = "Prise en charge de traitement expirée. Patient élligible en rediagnostic."
336
                    highlight = True
337
                else:
338
                    status = "Prise en charge de traitement expirée. La demande d'un renouvellement est possible."
339
                    highlight = True
340
            elif status[0] == 4:
341
                status = "Il existe une prise en charge de traitement mais qui ne prendra effet que le %s." % str(status[1])
342
            elif status[0] == 5:
343
                status = "Prise en charge de traitement en cours."
344
            elif status[0] == 6:
345
                status = "Prise en charge de traitement complète mais qui peut être prolongée."
346
                highlight = True
347
            elif status[0] == 7:
348
                status = "Prise en charge de traitement déjà prolongée complète se terminant le %s." % str(status[2])
349
            else:
350
                status = 'Statut inconnu.'
351
            ctx['hc_status'] = (status, highlight)
352
            if ctx['object'].last_state.status.type == "ACCUEIL":
353
                # Inscription automatique au premier acte facturable valide
354
                ctx['status'] = [STATES_BTN_MAPPER['FIN_ACCUEIL'],
355
                        STATES_BTN_MAPPER['DIAGNOSTIC'],
356
                        STATES_BTN_MAPPER['TRAITEMENT']]
357
            elif ctx['object'].last_state.status.type == "FIN_ACCUEIL":
358
                # Passage automatique en diagnostic ou traitement
359
                ctx['status'] = [STATES_BTN_MAPPER['ACCUEIL'],
360
                        STATES_BTN_MAPPER['DIAGNOSTIC'],
361
                        STATES_BTN_MAPPER['TRAITEMENT']]
362
            elif ctx['object'].last_state.status.type == "DIAGNOSTIC":
363
                # Passage automatique en traitement
364
                ctx['status'] = [STATES_BTN_MAPPER['TRAITEMENT'],
365
                        STATES_BTN_MAPPER['CLOS'],
366
                        STATES_BTN_MAPPER['ACCUEIL']]
367
            elif ctx['object'].last_state.status.type == "TRAITEMENT":
368
                # Passage automatique en diagnostic si on ajoute une prise en charge diagnostic,
369
                # ce qui est faisable dans l'onglet prise en charge par un bouton visible sous conditions
370
                ctx['status'] = [STATES_BTN_MAPPER['DIAGNOSTIC'],
371
                        STATES_BTN_MAPPER['CLOS'],
372
                        STATES_BTN_MAPPER['ACCUEIL']]
373
            elif ctx['object'].last_state.status.type == "CLOS":
374
                # Passage automatique en diagnostic ou traitement
375
                ctx['status'] = [STATES_BTN_MAPPER['DIAGNOSTIC'],
376
                        STATES_BTN_MAPPER['TRAITEMENT'],
377
                        STATES_BTN_MAPPER['ACCUEIL']]
378
            (acts_not_locked, days_not_locked, acts_not_valide,
379
            acts_not_billable, acts_pause, acts_per_hc, acts_losts) = \
380
                list_acts_for_billing_CMPP_2_per_patient(self.object,
381
                    datetime.today(), self.service)
382
            ctx['acts_losts'] = acts_losts
383
            ctx['acts_pause'] = acts_pause
384
            hcs_used = acts_per_hc.keys()
385
            if not hcs_used:
386
                ctx['hcs'] = [(hc, None) for hc in HealthCare.objects.filter(patient=self.object).order_by('-start_date')]
387
            else:
388
                ctx['hcs'] = []
389
                for hc in HealthCare.objects.filter(patient=self.object).order_by('-start_date'):
390
                    acts = None
391
                    if hasattr(hc, 'cmpphealthcarediagnostic') and hc.cmpphealthcarediagnostic in hcs_used:
392
                        acts = acts_per_hc[hc.cmpphealthcarediagnostic]
393
                    elif hasattr(hc, 'cmpphealthcaretreatment') and hc.cmpphealthcaretreatment in hcs_used:
394
                        acts = acts_per_hc[hc.cmpphealthcaretreatment]
395
                    ctx['hcs'].append((hc, acts))
396
        elif ctx['object'].service.name == "CAMSP":
397
            if ctx['object'].last_state.status.type == "ACCUEIL":
398
                ctx['status'] = [STATES_BTN_MAPPER['FIN_ACCUEIL'],
399
                        STATES_BTN_MAPPER['BILAN']]
400
            elif ctx['object'].last_state.status.type == "FIN_ACCUEIL":
401
                ctx['status'] = [STATES_BTN_MAPPER['ACCUEIL'],
402
                        STATES_BTN_MAPPER['BILAN'],
403
                        STATES_BTN_MAPPER['SURVEILLANCE'],
404
                        STATES_BTN_MAPPER['SUIVI'],
405
                        STATES_BTN_MAPPER['CLOS']]
406
            elif ctx['object'].last_state.status.type == "BILAN":
407
                ctx['status'] = [STATES_BTN_MAPPER['SURVEILLANCE'],
408
                        STATES_BTN_MAPPER['SUIVI'],
409
                        STATES_BTN_MAPPER['CLOS'],
410
                        STATES_BTN_MAPPER['ACCUEIL']]
411
            elif ctx['object'].last_state.status.type == "SURVEILLANCE":
412
                ctx['status'] = [STATES_BTN_MAPPER['SUIVI'],
413
                        STATES_BTN_MAPPER['CLOS'],
414
                        STATES_BTN_MAPPER['ACCUEIL'],
415
                        STATES_BTN_MAPPER['BILAN']]
416
            elif ctx['object'].last_state.status.type == "SUIVI":
417
                ctx['status'] = [STATES_BTN_MAPPER['CLOS'],
418
                        STATES_BTN_MAPPER['ACCUEIL'],
419
                        STATES_BTN_MAPPER['BILAN'],
420
                        STATES_BTN_MAPPER['SURVEILLANCE']]
421
            elif ctx['object'].last_state.status.type == "CLOS":
422
                ctx['status'] = [STATES_BTN_MAPPER['ACCUEIL'],
423
                        STATES_BTN_MAPPER['BILAN'],
424
                        STATES_BTN_MAPPER['SURVEILLANCE'],
425
                        STATES_BTN_MAPPER['SUIVI']]
426
        elif ctx['object'].service.name == "SESSAD TED" or ctx['object'].service.name == "SESSAD DYS":
427
            if ctx['object'].last_state.status.type == "ACCUEIL":
428
                ctx['status'] = [STATES_BTN_MAPPER['FIN_ACCUEIL'],
429
                        STATES_BTN_MAPPER['TRAITEMENT']]
430
            elif ctx['object'].last_state.status.type == "FIN_ACCUEIL":
431
                ctx['status'] = [STATES_BTN_MAPPER['ACCUEIL'],
432
                        STATES_BTN_MAPPER['TRAITEMENT'],
433
                        STATES_BTN_MAPPER['CLOS']]
434
            elif ctx['object'].last_state.status.type == "TRAITEMENT":
435
                ctx['status'] = [STATES_BTN_MAPPER['CLOS'],
436
                        STATES_BTN_MAPPER['ACCUEIL']]
437
            elif ctx['object'].last_state.status.type == "CLOS":
438
                ctx['status'] = [STATES_BTN_MAPPER['ACCUEIL'],
439
                        STATES_BTN_MAPPER['TRAITEMENT']]
440
            ctx['hcs'] = HealthCare.objects.filter(patient=self.object).order_by('-start_date')
441
        return ctx
442

    
443
    def form_valid(self, form):
444
        messages.add_message(self.request, messages.INFO, u'Modification enregistrée avec succès.')
445
        return super(PatientRecordView, self).form_valid(form)
446

    
447

    
448
patient_record = PatientRecordView.as_view()
449

    
450
class PatientRecordsHomepageView(cbv.ListView):
451
    model = PatientRecord
452
    template_name = 'dossiers/index.html'
453

    
454

    
455
    def _get_search_result(self, paginate_patient_records):
456
        patient_records = []
457
        for patient_record in paginate_patient_records:
458
            next_rdv = get_next_rdv(patient_record)
459
            last_rdv = get_last_rdv(patient_record)
460
            current_status = patient_record.last_state.status
461
            state = current_status.name
462
            state_class = current_status.type.lower()
463
            patient_records.append(
464
                    {
465
                        'object': patient_record,
466
                        'next_rdv': next_rdv,
467
                        'last_rdv': last_rdv,
468
                        'state': state,
469
                        'state_class': state_class
470
                        }
471
                    )
472
        return patient_records
473

    
474
    def get_queryset(self):
475
        first_name = self.request.GET.get('first_name')
476
        last_name = self.request.GET.get('last_name')
477
        paper_id = self.request.GET.get('paper_id')
478
        id = self.request.GET.get('id')
479
        social_security_id = self.request.GET.get('social_security_id')
480
        if not (first_name or last_name or paper_id or id or social_security_id):
481
            return None
482
        if (first_name and len(first_name) < 2) or (last_name and len(last_name) < 2):
483
            return None
484
        qs = super(PatientRecordsHomepageView, self).get_queryset()
485
        states = self.request.GET.getlist('states')
486
        if last_name:
487
            qs = qs.filter(last_name__istartswith=last_name)
488
        if first_name:
489
            qs = qs.filter(first_name__istartswith=first_name)
490
        if paper_id:
491
            qs = qs.filter(paper_id__startswith=paper_id)
492
        if id:
493
            qs = qs.filter(id__startswith=id)
494
        if social_security_id:
495
            qs = qs.filter(models.Q(social_security_id__startswith=social_security_id) | \
496
                models.Q(contacts__social_security_id__startswith=social_security_id))
497
        if states:
498
            qs = qs.filter(last_state__status__id__in=states)
499
        else:
500
            qs = qs.filter(last_state__status__type__in="")
501
        qs = qs.filter(service=self.service).order_by('last_name').\
502
                prefetch_related('last_state',
503
                        'patientcontact', 'last_state__status')
504
        return qs
505

    
506
    def get_context_data(self, **kwargs):
507
        ctx = super(PatientRecordsHomepageView, self).get_context_data(**kwargs)
508
        ctx['search_form'] = forms.SearchForm(service=self.service, data=self.request.GET or None)
509
        ctx['stats'] = [["Dossiers", 0]]
510
        for status in Status.objects.filter(services=self.service):
511
            ctx['stats'].append([status.name, 0])
512

    
513
        page = self.request.GET.get('page')
514
        if ctx['object_list']:
515
            patient_records = ctx['object_list'].filter()
516
        else:
517
            patient_records = []
518

    
519
        # TODO: use a sql query to do this
520
        for patient_record in patient_records:
521
            ctx['stats'][0][1] += 1
522
            for elem in ctx['stats']:
523
                if elem[0] == patient_record.last_state.status.name:
524
                    elem[1] += 1
525
        paginator = Paginator(patient_records, 50)
526
        try:
527
            paginate_patient_records = paginator.page(page)
528
        except PageNotAnInteger:
529
            paginate_patient_records = paginator.page(1)
530
        except EmptyPage:
531
            paginate_patient_records = paginator.page(paginator.num_pages)
532

    
533
        query = self.request.GET.copy()
534
        if 'page' in query:
535
            del query['page']
536
        ctx['query'] = query.urlencode()
537

    
538
        ctx['paginate_patient_records'] = paginate_patient_records
539
        ctx['patient_records'] = self._get_search_result(paginate_patient_records)
540
        return ctx
541

    
542
patientrecord_home = PatientRecordsHomepageView.as_view()
543

    
544
class PatientRecordDeleteView(DeleteView):
545
    model = PatientRecord
546
    success_url = ".."
547
    template_name = 'dossiers/patientrecord_confirm_delete.html'
548

    
549
patientrecord_delete = validator_only(PatientRecordDeleteView.as_view())
550

    
551

    
552
class PatientRecordPaperIDUpdateView(cbv.UpdateView):
553
    model = PatientRecord
554
    form_class = forms.PaperIDForm
555
    template_name = 'dossiers/generic_form.html'
556
    success_url = '../..'
557

    
558
update_paper_id = PatientRecordPaperIDUpdateView.as_view()
559

    
560

    
561
class NewSocialisationDurationView(cbv.CreateView):
562
    model = SocialisationDuration
563
    form_class = forms.SocialisationDurationForm
564
    template_name = 'dossiers/generic_form.html'
565
    success_url = '../view#tab=6'
566

    
567
    def get_success_url(self):
568
        return self.success_url
569

    
570
    def get(self, request, *args, **kwargs):
571
        if kwargs.has_key('patientrecord_id'):
572
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
573
        return super(NewSocialisationDurationView, self).get(request, *args, **kwargs)
574

    
575
    def form_valid(self, form):
576
        duration = form.save()
577
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
578
        patientrecord.socialisation_durations.add(duration)
579
        return HttpResponseRedirect(self.get_success_url())
580

    
581
new_socialisation_duration = NewSocialisationDurationView.as_view()
582

    
583
class UpdateSocialisationDurationView(cbv.UpdateView):
584
    model = SocialisationDuration
585
    form_class = forms.SocialisationDurationForm
586
    template_name = 'dossiers/generic_form.html'
587
    success_url = '../../view#tab=6'
588

    
589
    def get(self, request, *args, **kwargs):
590
        if kwargs.has_key('patientrecord_id'):
591
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
592
        return super(UpdateSocialisationDurationView, self).get(request, *args, **kwargs)
593

    
594
update_socialisation_duration = UpdateSocialisationDurationView.as_view()
595

    
596
class DeleteSocialisationDurationView(cbv.DeleteView):
597
    model = SocialisationDuration
598
    form_class = forms.SocialisationDurationForm
599
    template_name = 'dossiers/socialisationduration_confirm_delete.html'
600
    success_url = '../../view#tab=6'
601

    
602
delete_socialisation_duration = DeleteSocialisationDurationView.as_view()
603

    
604

    
605
class NewMDPHRequestView(cbv.CreateView):
606
    def get(self, request, *args, **kwargs):
607
        if kwargs.has_key('patientrecord_id'):
608
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
609
        return super(NewMDPHRequestView, self).get(request, *args, **kwargs)
610

    
611
    def form_valid(self, form):
612
        request = form.save()
613
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
614
        patientrecord.mdph_requests.add(request)
615
        return HttpResponseRedirect(self.success_url)
616

    
617
class UpdateMDPHRequestView(cbv.UpdateView):
618
    def get(self, request, *args, **kwargs):
619
        if kwargs.has_key('patientrecord_id'):
620
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
621
        return super(UpdateMDPHRequestView, self).get(request, *args, **kwargs)
622

    
623

    
624
new_mdph_request = \
625
    NewMDPHRequestView.as_view(model=MDPHRequest,
626
        template_name = 'dossiers/generic_form.html',
627
        success_url = '../view#tab=6',
628
        form_class=forms.MDPHRequestForm)
629
update_mdph_request = \
630
    UpdateMDPHRequestView.as_view(model=MDPHRequest,
631
        template_name = 'dossiers/generic_form.html',
632
        success_url = '../../view#tab=6',
633
        form_class=forms.MDPHRequestForm)
634
delete_mdph_request = \
635
    cbv.DeleteView.as_view(model=MDPHRequest,
636
        template_name = 'dossiers/generic_confirm_delete.html',
637
        success_url = '../../view#tab=6')
638

    
639
class NewMDPHResponseView(cbv.CreateView):
640
    def get(self, request, *args, **kwargs):
641
        if kwargs.has_key('patientrecord_id'):
642
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
643
        return super(NewMDPHResponseView, self).get(request, *args, **kwargs)
644

    
645
    def form_valid(self, form):
646
        response = form.save()
647
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
648
        patientrecord.mdph_responses.add(response)
649
        return HttpResponseRedirect(self.success_url)
650

    
651
class UpdateMDPHResponseView(cbv.UpdateView):
652
    def get(self, request, *args, **kwargs):
653
        if kwargs.has_key('patientrecord_id'):
654
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
655
        return super(UpdateMDPHResponseView, self).get(request, *args, **kwargs)
656

    
657

    
658
new_mdph_response = \
659
    NewMDPHResponseView.as_view(model=MDPHResponse,
660
        template_name = 'dossiers/generic_form.html',
661
        success_url = '../view#tab=6',
662
        form_class=forms.MDPHResponseForm)
663
update_mdph_response = \
664
    UpdateMDPHResponseView.as_view(model=MDPHResponse,
665
        template_name = 'dossiers/generic_form.html',
666
        success_url = '../../view#tab=6',
667
        form_class=forms.MDPHResponseForm)
668
delete_mdph_response = \
669
    cbv.DeleteView.as_view(model=MDPHResponse,
670
        template_name = 'dossiers/generic_confirm_delete.html',
671
        success_url = '../../view#tab=6')
672

    
673

    
674
class UpdatePatientStateView(cbv.ServiceFormMixin, cbv.UpdateView):
675

    
676
    def get_initial(self):
677
        initial = super(UpdatePatientStateView, self).get_initial()
678
        initial['date_selected'] = self.object.date_selected.date()
679
        return initial
680

    
681
    def get(self, request, *args, **kwargs):
682
        if kwargs.has_key('patientrecord_id'):
683
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
684
        return super(UpdatePatientStateView, self).get(request, *args, **kwargs)
685

    
686
class DeletePatientView(cbv.DeleteView):
687

    
688
    def delete(self, request, *args, **kwargs):
689
        self.object = self.get_object()
690
        if self.object == self.object.patient.last_state:
691
            status = self.object.patient.filestate_set.all().order_by('-created')
692
            if len(status) > 1:
693
                self.object.patient.last_state = status[1]
694
                self.object.patient.save()
695
            else:
696
                # TODO return an error here
697
                return HttpResponseRedirect(self.get_success_url())
698
        self.object.delete()
699
        return HttpResponseRedirect(self.get_success_url())
700

    
701

    
702
update_patient_state = \
703
    UpdatePatientStateView.as_view(model=FileState,
704
        template_name = 'dossiers/generic_form.html',
705
        success_url = '../../view#tab=0',
706
        form_class=forms.PatientStateForm)
707
delete_patient_state = \
708
    DeletePatientView.as_view(model=FileState,
709
        template_name = 'dossiers/generic_confirm_delete.html',
710
        success_url = '../../view#tab=0')
711

    
712

    
713
class GenerateRtfFormView(cbv.FormView):
714
    template_name = 'dossiers/generate_rtf_form.html'
715
    form_class = forms.GenerateRtfForm
716
    success_url = './view#tab=0'
717

    
718
    def get_context_data(self, **kwargs):
719
        ctx = super(GenerateRtfFormView, self).get_context_data(**kwargs)
720
        ctx['object'] = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
721
        ctx['service_id'] = self.service.id
722
        if self.request.GET.get('event-id'):
723
            date = self.request.GET.get('date')
724
            date = datetime.strptime(date, '%Y-%m-%d').date()
725
            appointment = Appointment()
726
            event = EventWithAct.objects.get(id=self.request.GET.get('event-id'))
727
            event = event.today_occurrence(date)
728
            appointment.init_from_event(event, self.service)
729
            ctx['appointment'] = appointment
730
        return ctx
731

    
732
    def form_valid(self, form):
733
        patient = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
734
        template_filename = form.cleaned_data.get('template_filename')
735
        dest_filename = datetime.now().strftime('%Y-%m-%d--%H:%M') + '--' + template_filename
736
        from_path = os.path.join(settings.RTF_TEMPLATES_DIRECTORY, template_filename)
737
        to_path = os.path.join(patient.get_ondisk_directory(self.service.name), dest_filename)
738
        vars = {'AD11': '', 'AD12': '', 'AD13': '', 'AD14': '', 'AD15': '',
739
                'JOU1': datetime.today().strftime('%d/%m/%Y'),
740
                'VIL1': u'Saint-Étienne',
741
                'PRE1': form.cleaned_data.get('first_name'),
742
                'NOM1': form.cleaned_data.get('last_name'),
743
                'DPA1': form.cleaned_data.get('appointment_intervenants')
744
               }
745
        for i, line in enumerate(form.cleaned_data.get('address').splitlines()):
746
            vars['AD%d' % (11+i)] = line
747
        make_doc_from_template(from_path, to_path, vars)
748

    
749
        client_dir = patient.get_client_side_directory(self.service.name)
750
        if not client_dir:
751
            response = HttpResponse(mimetype='text/rtf')
752
            response['Content-Disposition'] = 'attachment; filename="%s"' % dest_filename
753
            response.write(file(to_path).read())
754
            return response
755
        else:
756
            class LocalFileHttpResponseRedirect(HttpResponseRedirect):
757
                allowed_schemes = ['file']
758
            client_filepath = os.path.join(client_dir, dest_filename)
759
            return LocalFileHttpResponseRedirect('file://' + client_filepath)
760

    
761
generate_rtf_form = GenerateRtfFormView.as_view()
762

    
763

    
764
class PatientRecordsQuotationsView(cbv.ListView):
765
    model = PatientRecord
766
    template_name = 'dossiers/quotations.html'
767

    
768
    def _get_search_result(self, paginate_patient_records):
769
        patient_records = []
770
        for patient_record in paginate_patient_records:
771
            next_rdv = get_next_rdv(patient_record)
772
            last_rdv = get_last_rdv(patient_record)
773
            current_state = patient_record.get_current_state()
774
            state = current_state.status.name
775
            state_class = current_state.status.type.lower()
776
            patient_records.append(
777
                    {
778
                        'object': patient_record,
779
                        'state': state,
780
                        'state_class': state_class
781
                        }
782
                    )
783
        return patient_records
784

    
785
    def get_queryset(self):
786
        form = forms.QuotationsForm(data=self.request.GET or None)
787
        qs = super(PatientRecordsQuotationsView, self).get_queryset()
788
        without_quotations = self.request.GET.get('without_quotations')
789
        if without_quotations:
790
            qs = qs.filter(mises_1=None).filter(mises_2=None).filter(mises_3=None)
791
        states = self.request.GET.getlist('states')
792
        qs = qs.filter(last_state__status__id__in=states)
793

    
794
        try:
795
            date_actes_start = datetime.strptime(form.data['date_actes_start'], "%d/%m/%Y")
796
            qs = qs.filter(act_set__date__gte=date_actes_start.date())
797
        except (ValueError, KeyError):
798
            pass
799
        try:
800
            date_actes_end = datetime.strptime(form.data['date_actes_end'], "%d/%m/%Y")
801
            qs = qs.filter(act_set__date__lte=date_actes_end.date())
802
        except (ValueError, KeyError):
803
            pass
804
        qs = qs.filter(service=self.service).order_by('last_name').prefetch_related()
805
        return qs
806

    
807
    def get_context_data(self, **kwargs):
808
        ctx = super(PatientRecordsQuotationsView, self).get_context_data(**kwargs)
809
        ctx['search_form'] = forms.QuotationsForm(data=self.request.GET or None,
810
                service=self.service)
811
        patient_records = []
812
        page = self.request.GET.get('page')
813
        paginator = Paginator(ctx['object_list'].filter(), 50)
814
        try:
815
            paginate_patient_records = paginator.page(page)
816
        except PageNotAnInteger:
817
            paginate_patient_records = paginator.page(1)
818
        except EmptyPage:
819
            paginate_patient_records = paginator.page(paginator.num_pages)
820

    
821
        ctx['patient_records'] = self._get_search_result(paginate_patient_records)
822
        ctx['paginate_patient_records'] = paginate_patient_records
823

    
824
        query = self.request.GET.copy()
825
        if 'page' in query:
826
            del query['page']
827
        ctx['query'] = query.urlencode()
828

    
829
        return ctx
830

    
831
patientrecord_quotations = PatientRecordsQuotationsView.as_view()
832

    
833

    
834
class CreateDirectoryView(View, cbv.ServiceViewMixin):
835
    def post(self, request, *args, **kwargs):
836
        patient = PatientRecord.objects.get(id=kwargs['patientrecord_id'])
837
        service = Service.objects.get(slug=kwargs['service'])
838
        patient.get_ondisk_directory(service.name)
839
        messages.add_message(self.request, messages.INFO, u'Répertoire patient créé.')
840
        return HttpResponseRedirect('view')
841

    
842
create_directory = CreateDirectoryView.as_view()
(9-9/9)