Project

General

Profile

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

calebasse / calebasse / dossiers / views.py @ b4310641

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
from django.core.files import File
16
from django.forms import Form
17

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

    
33
from calebasse.decorators import validator_only
34

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

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

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

    
75
    def post(self, request, *args, **kwarg):
76
        self.user = request.user
77
        return super(NewPatientRecordView, self).post(request, *args, **kwarg)
78

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

    
84
    def get_success_url(self):
85
        return '%s/view' % self.patient.id
86

    
87
new_patient_record = NewPatientRecordView.as_view()
88

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

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

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

    
105
new_patient_contact = NewPatientContactView.as_view()
106

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

    
113
update_patient_contact = UpdatePatientContactView.as_view()
114

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

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

    
131
delete_patient_contact = DeletePatientContactView.as_view()
132

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

    
139
    def get_success_url(self):
140
        return self.success_url
141

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

    
149
new_patient_address = NewPatientAddressView.as_view()
150

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

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

    
161
update_patient_address = UpdatePatientAddressView.as_view()
162

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

    
169
delete_patient_address = DeletePatientAddressView.as_view()
170

    
171

    
172
class NewHealthCareView(cbv.CreateView):
173

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

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

    
223

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

    
229

    
230
    def post(self, request, *args, **kwarg):
231
        self.user = request.user
232
        return super(StateFormView, self).post(request, *args, **kwarg)
233

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

    
242
state_form = StateFormView.as_view()
243

    
244

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

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

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

    
317
        ctx['missing_policy'] = False
318
        if not self.object.policyholder or \
319
                not self.object.policyholder.health_center or \
320
                not self.object.policyholder.social_security_id:
321
            ctx['missing_policy'] = True
322

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

    
448
    def form_valid(self, form):
449
        messages.add_message(self.request, messages.INFO, u'Modification enregistrée avec succès.')
450
        return super(PatientRecordView, self).form_valid(form)
451

    
452

    
453
patient_record = PatientRecordView.as_view()
454

    
455
class PatientRecordsHomepageView(cbv.ListView):
456
    model = PatientRecord
457
    template_name = 'dossiers/index.html'
458

    
459

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

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

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

    
518
        page = self.request.GET.get('page')
519
        if ctx['object_list']:
520
            patient_records = ctx['object_list'].filter()
521
        else:
522
            patient_records = []
523

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

    
538
        query = self.request.GET.copy()
539
        if 'page' in query:
540
            del query['page']
541
        ctx['query'] = query.urlencode()
542

    
543
        ctx['paginate_patient_records'] = paginate_patient_records
544
        ctx['patient_records'] = self._get_search_result(paginate_patient_records)
545
        return ctx
546

    
547
patientrecord_home = PatientRecordsHomepageView.as_view()
548

    
549
class PatientRecordDeleteView(DeleteView):
550
    model = PatientRecord
551
    success_url = ".."
552
    template_name = 'dossiers/patientrecord_confirm_delete.html'
553

    
554
patientrecord_delete = validator_only(PatientRecordDeleteView.as_view())
555

    
556

    
557
class PatientRecordPaperIDUpdateView(cbv.UpdateView):
558
    model = PatientRecord
559
    form_class = forms.PaperIDForm
560
    template_name = 'dossiers/generic_form.html'
561
    success_url = '../..'
562

    
563
update_paper_id = PatientRecordPaperIDUpdateView.as_view()
564

    
565

    
566
class NewSocialisationDurationView(cbv.CreateView):
567
    model = SocialisationDuration
568
    form_class = forms.SocialisationDurationForm
569
    template_name = 'dossiers/generic_form.html'
570
    success_url = '../view#tab=6'
571

    
572
    def get_success_url(self):
573
        return self.success_url
574

    
575
    def get(self, request, *args, **kwargs):
576
        if kwargs.has_key('patientrecord_id'):
577
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
578
        return super(NewSocialisationDurationView, self).get(request, *args, **kwargs)
579

    
580
    def form_valid(self, form):
581
        duration = form.save()
582
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
583
        patientrecord.socialisation_durations.add(duration)
584
        return HttpResponseRedirect(self.get_success_url())
585

    
586
new_socialisation_duration = NewSocialisationDurationView.as_view()
587

    
588
class UpdateSocialisationDurationView(cbv.UpdateView):
589
    model = SocialisationDuration
590
    form_class = forms.SocialisationDurationForm
591
    template_name = 'dossiers/generic_form.html'
592
    success_url = '../../view#tab=6'
593

    
594
    def get(self, request, *args, **kwargs):
595
        if kwargs.has_key('patientrecord_id'):
596
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
597
        return super(UpdateSocialisationDurationView, self).get(request, *args, **kwargs)
598

    
599
update_socialisation_duration = UpdateSocialisationDurationView.as_view()
600

    
601
class DeleteSocialisationDurationView(cbv.DeleteView):
602
    model = SocialisationDuration
603
    form_class = forms.SocialisationDurationForm
604
    template_name = 'dossiers/socialisationduration_confirm_delete.html'
605
    success_url = '../../view#tab=6'
606

    
607
delete_socialisation_duration = DeleteSocialisationDurationView.as_view()
608

    
609

    
610
class NewMDPHRequestView(cbv.CreateView):
611
    def get(self, request, *args, **kwargs):
612
        if kwargs.has_key('patientrecord_id'):
613
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
614
        return super(NewMDPHRequestView, self).get(request, *args, **kwargs)
615

    
616
    def form_valid(self, form):
617
        request = form.save()
618
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
619
        patientrecord.mdph_requests.add(request)
620
        return HttpResponseRedirect(self.success_url)
621

    
622
class UpdateMDPHRequestView(cbv.UpdateView):
623
    def get(self, request, *args, **kwargs):
624
        if kwargs.has_key('patientrecord_id'):
625
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
626
        return super(UpdateMDPHRequestView, self).get(request, *args, **kwargs)
627

    
628

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

    
644
class NewMDPHResponseView(cbv.CreateView):
645
    def get(self, request, *args, **kwargs):
646
        if kwargs.has_key('patientrecord_id'):
647
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
648
        return super(NewMDPHResponseView, self).get(request, *args, **kwargs)
649

    
650
    def form_valid(self, form):
651
        response = form.save()
652
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
653
        patientrecord.mdph_responses.add(response)
654
        return HttpResponseRedirect(self.success_url)
655

    
656
class UpdateMDPHResponseView(cbv.UpdateView):
657
    def get(self, request, *args, **kwargs):
658
        if kwargs.has_key('patientrecord_id'):
659
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
660
        return super(UpdateMDPHResponseView, self).get(request, *args, **kwargs)
661

    
662

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

    
678

    
679
class UpdatePatientStateView(cbv.ServiceFormMixin, cbv.UpdateView):
680

    
681
    def get_initial(self):
682
        initial = super(UpdatePatientStateView, self).get_initial()
683
        initial['date_selected'] = self.object.date_selected.date()
684
        return initial
685

    
686
    def get(self, request, *args, **kwargs):
687
        if kwargs.has_key('patientrecord_id'):
688
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
689
        return super(UpdatePatientStateView, self).get(request, *args, **kwargs)
690

    
691
class DeletePatientView(cbv.DeleteView):
692

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

    
706

    
707
update_patient_state = \
708
    UpdatePatientStateView.as_view(model=FileState,
709
        template_name = 'dossiers/generic_form.html',
710
        success_url = '../../view#tab=0',
711
        form_class=forms.PatientStateForm)
712
delete_patient_state = \
713
    DeletePatientView.as_view(model=FileState,
714
        template_name = 'dossiers/generic_confirm_delete.html',
715
        success_url = '../../view#tab=0')
716

    
717

    
718
class GenerateRtfFormView(cbv.FormView):
719
    template_name = 'dossiers/generate_rtf_form.html'
720
    form_class = forms.GenerateRtfForm
721
    success_url = './view#tab=0'
722

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

    
737
    def form_valid(self, form, **kwargs):
738
        ctx = self.get_context_data(**kwargs)
739
        patient = ctx['object']
740
        appointment = ctx['appointment']
741
        template_filename = form.cleaned_data.get('template_filename')
742
        dest_filename = datetime.now().strftime('%Y-%m-%d--%H:%M:%S') + '--' + template_filename
743
        from_path = os.path.join(settings.RTF_TEMPLATES_DIRECTORY, template_filename)
744
        to_path = ''
745
        persistent = True
746
        if settings.USE_PATIENT_FILE_RTF_REPOSITORY_DIRECTORY \
747
                or settings.RTF_REPOSITORY_DIRECTORY:
748
            if settings.USE_PATIENT_FILE_RTF_REPOSITORY_DIRECTORY:
749
                to_path = patient.get_ondisk_directory(self.service.name)
750
            if settings.RTF_REPOSITORY_DIRECTORY:
751
                to_path = os.path.join(to_path,
752
                    settings.RTF_REPOSITORY_DIRECTORY)
753
            to_path = os.path.join(to_path, dest_filename)
754
        else:
755
            # else : use temporary files
756
            persistent = False
757
            to_path = dest_filename
758
        variables = {'AD11': '', 'AD12': '', 'AD13': '', 'AD14': '',
759
            'AD15': '', 'AD18': '',
760
            'JOU1': datetime.today().strftime('%d/%m/%Y'),
761
            'VIL1': u'Saint-Étienne',
762
            'RDV1': '', 'HEU1': '', 'THE1': '', 'DPA1': '',
763
            'NOM1': '', 'PRE1': '', 'NAI1': '', 'NUM2': '',
764
            'NOM2': '', 'PRE2': '', 'TPA1': '', 'NSS1': '',
765
            'TR01': '', 'TR02': '', 'TR03': '', 'TR04': '', 'TR05': '',
766
            'AD16': '', 'AD17': '', 'AD19': '',
767
            'AD21': '', 'AD22': '', 'AD23': '', 'AD24': '', 'AD25': '',
768
            'AD26': '', 'AD27': '', 'AD28': '', 'AD29': '',
769
        }
770
        if appointment:
771
            variables['RDV1'] = appointment.date
772
            variables['HEU1'] = appointment.begin_hour
773
            variables['THE1'] = ' '.join([str(i) for i in appointment.workers])# ou DPA1?
774
            variables['DPA1'] = variables['THE1']
775
        if patient:
776
            variables['NOM1'] = patient.last_name
777
            variables['PRE1'] = patient.first_name
778
            if patient.birthdate :
779
                variables['NAI1'] = patient.birthdate.strftime('%d/%m/%Y')
780
            variables['NUM2'] = patient.paper_id
781
            if patient.policyholder:
782
                variables['NOM2'] = patient.policyholder.last_name
783
                variables['PRE2'] = patient.policyholder.first_name
784
                variables['TPA1'] = patient.policyholder.health_center.name
785
                if patient.policyholder.social_security_id:
786
                    key = str(patient.policyholder.get_control_key())
787
                    if len(key) == 1:
788
                        key = '0' + key
789
                    variables['NSS1'] = \
790
                        ' '.join([patient.policyholder.social_security_id,
791
                            key])
792
            if patient.transportcompany:
793
                variables['TR01'] = patient.transportcompany.name
794
                variables['TR02'] = patient.transportcompany.address
795
                variables['TR03'] = patient.transportcompany.address_complement
796
                variables['TR04'] = patient.transportcompany.zip_code
797
                variables['TR05'] = patient.transportcompany.city
798
        variables['AD18'] = form.cleaned_data.get('phone_address') or ''
799
        for i, line in enumerate(form.cleaned_data.get('address').splitlines()):
800
            variables['AD%d' % (11+i)] = line
801
            if i == 4:
802
                break
803

    
804
        filename = make_doc_from_template(from_path, to_path, variables,
805
            persistent)
806

    
807
        client_dir = patient.get_client_side_directory(self.service.name)
808
        if not client_dir:
809
            content = File(file(filename))
810
            response = HttpResponse(content,'text/rtf')
811
            response['Content-Length'] = content.size
812
            response['Content-Disposition'] = 'attachment; filename="%s"' % dest_filename
813
            return response
814
        else:
815
            class LocalFileHttpResponseRedirect(HttpResponseRedirect):
816
                allowed_schemes = ['file']
817
            client_filepath = os.path.join(client_dir, dest_filename)
818
            return LocalFileHttpResponseRedirect('file://' + client_filepath)
819

    
820
generate_rtf_form = GenerateRtfFormView.as_view()
821

    
822

    
823
class PatientRecordsQuotationsView(cbv.ListView):
824
    model = PatientRecord
825
    template_name = 'dossiers/quotations.html'
826

    
827
    def _get_search_result(self, paginate_patient_records):
828
        patient_records = []
829
        for patient_record in paginate_patient_records:
830
            next_rdv = get_next_rdv(patient_record)
831
            last_rdv = get_last_rdv(patient_record)
832
            current_state = patient_record.get_current_state()
833
            state = current_state.status.name
834
            state_class = current_state.status.type.lower()
835
            patient_records.append(
836
                    {
837
                        'object': patient_record,
838
                        'state': state,
839
                        'state_class': state_class
840
                        }
841
                    )
842
        return patient_records
843

    
844
    def get_queryset(self):
845
        form = forms.QuotationsForm(data=self.request.GET or None)
846
        qs = super(PatientRecordsQuotationsView, self).get_queryset()
847
        without_quotations = self.request.GET.get('without_quotations')
848
        if without_quotations:
849
            qs = qs.filter(mises_1=None).filter(mises_2=None).filter(mises_3=None)
850
        states = self.request.GET.getlist('states')
851
        qs = qs.filter(last_state__status__id__in=states)
852

    
853
        try:
854
            date_actes_start = datetime.strptime(form.data['date_actes_start'], "%d/%m/%Y")
855
            qs = qs.filter(act_set__date__gte=date_actes_start.date())
856
        except (ValueError, KeyError):
857
            pass
858
        try:
859
            date_actes_end = datetime.strptime(form.data['date_actes_end'], "%d/%m/%Y")
860
            qs = qs.filter(act_set__date__lte=date_actes_end.date())
861
        except (ValueError, KeyError):
862
            pass
863
        qs = qs.filter(service=self.service).order_by('last_name').prefetch_related()
864
        return qs
865

    
866
    def get_context_data(self, **kwargs):
867
        ctx = super(PatientRecordsQuotationsView, self).get_context_data(**kwargs)
868
        ctx['search_form'] = forms.QuotationsForm(data=self.request.GET or None,
869
                service=self.service)
870
        patient_records = []
871
        page = self.request.GET.get('page')
872
        paginator = Paginator(ctx['object_list'].filter(), 50)
873
        try:
874
            paginate_patient_records = paginator.page(page)
875
        except PageNotAnInteger:
876
            paginate_patient_records = paginator.page(1)
877
        except EmptyPage:
878
            paginate_patient_records = paginator.page(paginator.num_pages)
879

    
880
        ctx['patient_records'] = self._get_search_result(paginate_patient_records)
881
        ctx['paginate_patient_records'] = paginate_patient_records
882

    
883
        query = self.request.GET.copy()
884
        if 'page' in query:
885
            del query['page']
886
        ctx['query'] = query.urlencode()
887

    
888
        return ctx
889

    
890
patientrecord_quotations = PatientRecordsQuotationsView.as_view()
891

    
892

    
893
class CreateDirectoryView(View, cbv.ServiceViewMixin):
894
    def post(self, request, *args, **kwargs):
895
        patient = PatientRecord.objects.get(id=kwargs['patientrecord_id'])
896
        service = Service.objects.get(slug=kwargs['service'])
897
        patient.get_ondisk_directory(service.name)
898
        messages.add_message(self.request, messages.INFO, u'Répertoire patient créé.')
899
        return HttpResponseRedirect('view')
900

    
901
create_directory = CreateDirectoryView.as_view()
902

    
903
class GenerateTransportPrescriptionFormView(cbv.FormView):
904
    template_name = 'dossiers/generate_transport_prescription_form.html'
905
    form_class = Form
906
    success_url = './view#tab=1'
907

    
908
    def get_context_data(self, **kwargs):
909
        ctx = super(GenerateTransportPrescriptionFormView, self).get_context_data(**kwargs)
910
        ctx['object'] = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
911
        return ctx
912

    
913
    def form_valid(self, form):
914
        patient = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
915
        address = PatientAddress.objects.get(id=form.data['address_id'])
916
        path = render_transport(patient, address)
917
        content = File(file(path))
918
        response = HttpResponse(content,'application/pdf')
919
        response['Content-Length'] = content.size
920
        response['Content-Disposition'] = \
921
            'attachment; filename="cerfa-transport-%s-%s.pdf"' \
922
            % (patient.last_name.upper(), patient.first_name)
923
        return response
924

    
925
prescription_transport = GenerateTransportPrescriptionFormView.as_view()
(11-11/11)