Project

General

Profile

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

calebasse / calebasse / dossiers / views.py @ 523c5aaf

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
from django.utils import formats
18

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

    
35
from calebasse.decorators import validator_only
36

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

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

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

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

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

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

    
89
new_patient_record = NewPatientRecordView.as_view()
90

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

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

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

    
107
new_patient_contact = NewPatientContactView.as_view()
108

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

    
115
update_patient_contact = UpdatePatientContactView.as_view()
116

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

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

    
133
delete_patient_contact = DeletePatientContactView.as_view()
134

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

    
141
    def get_success_url(self):
142
        return self.success_url
143

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

    
151
new_patient_address = NewPatientAddressView.as_view()
152

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

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

    
163
update_patient_address = UpdatePatientAddressView.as_view()
164

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

    
171
delete_patient_address = DeletePatientAddressView.as_view()
172

    
173

    
174
class NewHealthCareView(cbv.CreateView):
175

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

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

    
225

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

    
231

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

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

    
244
state_form = StateFormView.as_view()
245

    
246

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

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

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

    
319
        ctx['missing_policy'] = False
320
        if not self.object.policyholder or \
321
                not self.object.policyholder.health_center or \
322
                not self.object.policyholder.social_security_id:
323
            ctx['missing_policy'] = True
324
        ctx['missing_birthdate'] = False
325
        if not self.object.birthdate:
326
            ctx['missing_birthdate'] = True
327

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

    
457
    def form_valid(self, form):
458
        messages.add_message(self.request, messages.INFO, u'Modification enregistrée avec succès.')
459
        return super(PatientRecordView, self).form_valid(form)
460

    
461

    
462
patient_record = PatientRecordView.as_view()
463

    
464
class PatientRecordsHomepageView(cbv.ListView):
465
    model = PatientRecord
466
    template_name = 'dossiers/index.html'
467

    
468

    
469
    def _get_search_result(self, paginate_patient_records):
470
        patient_records = []
471
        for patient_record in paginate_patient_records:
472
            next_rdv = get_next_rdv(patient_record)
473
            last_rdv = get_last_rdv(patient_record)
474
            current_status = patient_record.last_state.status
475
            state = current_status.name
476
            state_class = current_status.type.lower()
477
            patient_records.append(
478
                    {
479
                        'object': patient_record,
480
                        'next_rdv': next_rdv,
481
                        'last_rdv': last_rdv,
482
                        'state': state,
483
                        'state_class': state_class
484
                        }
485
                    )
486
        return patient_records
487

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

    
520
    def get_context_data(self, **kwargs):
521
        ctx = super(PatientRecordsHomepageView, self).get_context_data(**kwargs)
522
        ctx['search_form'] = forms.SearchForm(service=self.service, data=self.request.GET or None)
523
        ctx['stats'] = [["Dossiers", 0]]
524
        for status in Status.objects.filter(services=self.service):
525
            ctx['stats'].append([status.name, 0])
526

    
527
        page = self.request.GET.get('page')
528
        if ctx['object_list']:
529
            patient_records = ctx['object_list'].filter()
530
        else:
531
            patient_records = []
532

    
533
        # TODO: use a sql query to do this
534
        for patient_record in patient_records:
535
            ctx['stats'][0][1] += 1
536
            for elem in ctx['stats']:
537
                if elem[0] == patient_record.last_state.status.name:
538
                    elem[1] += 1
539
        paginator = Paginator(patient_records, 50)
540
        try:
541
            paginate_patient_records = paginator.page(page)
542
        except PageNotAnInteger:
543
            paginate_patient_records = paginator.page(1)
544
        except EmptyPage:
545
            paginate_patient_records = paginator.page(paginator.num_pages)
546

    
547
        query = self.request.GET.copy()
548
        if 'page' in query:
549
            del query['page']
550
        ctx['query'] = query.urlencode()
551

    
552
        ctx['paginate_patient_records'] = paginate_patient_records
553
        ctx['patient_records'] = self._get_search_result(paginate_patient_records)
554
        return ctx
555

    
556
patientrecord_home = PatientRecordsHomepageView.as_view()
557

    
558
class PatientRecordDeleteView(DeleteView):
559
    model = PatientRecord
560
    success_url = ".."
561
    template_name = 'dossiers/patientrecord_confirm_delete.html'
562

    
563
patientrecord_delete = validator_only(PatientRecordDeleteView.as_view())
564

    
565

    
566
class PatientRecordPaperIDUpdateView(cbv.UpdateView):
567
    model = PatientRecord
568
    form_class = forms.PaperIDForm
569
    template_name = 'dossiers/generic_form.html'
570
    success_url = '../..'
571

    
572
update_paper_id = PatientRecordPaperIDUpdateView.as_view()
573

    
574

    
575
class NewSocialisationDurationView(cbv.CreateView):
576
    model = SocialisationDuration
577
    form_class = forms.SocialisationDurationForm
578
    template_name = 'dossiers/generic_form.html'
579
    success_url = '../view#tab=6'
580

    
581
    def get_success_url(self):
582
        return self.success_url
583

    
584
    def get(self, request, *args, **kwargs):
585
        if kwargs.has_key('patientrecord_id'):
586
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
587
        return super(NewSocialisationDurationView, self).get(request, *args, **kwargs)
588

    
589
    def form_valid(self, form):
590
        duration = form.save()
591
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
592
        patientrecord.socialisation_durations.add(duration)
593
        return HttpResponseRedirect(self.get_success_url())
594

    
595
new_socialisation_duration = NewSocialisationDurationView.as_view()
596

    
597
class UpdateSocialisationDurationView(cbv.UpdateView):
598
    model = SocialisationDuration
599
    form_class = forms.SocialisationDurationForm
600
    template_name = 'dossiers/generic_form.html'
601
    success_url = '../../view#tab=6'
602

    
603
    def get(self, request, *args, **kwargs):
604
        if kwargs.has_key('patientrecord_id'):
605
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
606
        return super(UpdateSocialisationDurationView, self).get(request, *args, **kwargs)
607

    
608
update_socialisation_duration = UpdateSocialisationDurationView.as_view()
609

    
610
class DeleteSocialisationDurationView(cbv.DeleteView):
611
    model = SocialisationDuration
612
    form_class = forms.SocialisationDurationForm
613
    template_name = 'dossiers/socialisationduration_confirm_delete.html'
614
    success_url = '../../view#tab=6'
615

    
616
delete_socialisation_duration = DeleteSocialisationDurationView.as_view()
617

    
618

    
619
class NewMDPHRequestView(cbv.CreateView):
620
    def get(self, request, *args, **kwargs):
621
        if kwargs.has_key('patientrecord_id'):
622
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
623
        return super(NewMDPHRequestView, self).get(request, *args, **kwargs)
624

    
625
    def form_valid(self, form):
626
        request = form.save()
627
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
628
        patientrecord.mdph_requests.add(request)
629
        return HttpResponseRedirect(self.success_url)
630

    
631
class UpdateMDPHRequestView(cbv.UpdateView):
632
    def get(self, request, *args, **kwargs):
633
        if kwargs.has_key('patientrecord_id'):
634
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
635
        return super(UpdateMDPHRequestView, self).get(request, *args, **kwargs)
636

    
637

    
638
new_mdph_request = \
639
    NewMDPHRequestView.as_view(model=MDPHRequest,
640
        template_name = 'dossiers/generic_form.html',
641
        success_url = '../view#tab=6',
642
        form_class=forms.MDPHRequestForm)
643
update_mdph_request = \
644
    UpdateMDPHRequestView.as_view(model=MDPHRequest,
645
        template_name = 'dossiers/generic_form.html',
646
        success_url = '../../view#tab=6',
647
        form_class=forms.MDPHRequestForm)
648
delete_mdph_request = \
649
    cbv.DeleteView.as_view(model=MDPHRequest,
650
        template_name = 'dossiers/generic_confirm_delete.html',
651
        success_url = '../../view#tab=6')
652

    
653
class NewMDPHResponseView(cbv.CreateView):
654
    def get(self, request, *args, **kwargs):
655
        if kwargs.has_key('patientrecord_id'):
656
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
657
        return super(NewMDPHResponseView, self).get(request, *args, **kwargs)
658

    
659
    def form_valid(self, form):
660
        response = form.save()
661
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
662
        patientrecord.mdph_responses.add(response)
663
        return HttpResponseRedirect(self.success_url)
664

    
665
class UpdateMDPHResponseView(cbv.UpdateView):
666
    def get(self, request, *args, **kwargs):
667
        if kwargs.has_key('patientrecord_id'):
668
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
669
        return super(UpdateMDPHResponseView, self).get(request, *args, **kwargs)
670

    
671

    
672
new_mdph_response = \
673
    NewMDPHResponseView.as_view(model=MDPHResponse,
674
        template_name = 'dossiers/generic_form.html',
675
        success_url = '../view#tab=6',
676
        form_class=forms.MDPHResponseForm)
677
update_mdph_response = \
678
    UpdateMDPHResponseView.as_view(model=MDPHResponse,
679
        template_name = 'dossiers/generic_form.html',
680
        success_url = '../../view#tab=6',
681
        form_class=forms.MDPHResponseForm)
682
delete_mdph_response = \
683
    cbv.DeleteView.as_view(model=MDPHResponse,
684
        template_name = 'dossiers/generic_confirm_delete.html',
685
        success_url = '../../view#tab=6')
686

    
687

    
688
class UpdatePatientStateView(cbv.ServiceFormMixin, cbv.UpdateView):
689

    
690
    def get_initial(self):
691
        initial = super(UpdatePatientStateView, self).get_initial()
692
        initial['date_selected'] = self.object.date_selected.date()
693
        return initial
694

    
695
    def get(self, request, *args, **kwargs):
696
        if kwargs.has_key('patientrecord_id'):
697
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
698
        return super(UpdatePatientStateView, self).get(request, *args, **kwargs)
699

    
700
class DeletePatientView(cbv.DeleteView):
701

    
702
    def delete(self, request, *args, **kwargs):
703
        self.object = self.get_object()
704
        if self.object == self.object.patient.last_state:
705
            status = self.object.patient.filestate_set.all().order_by('-created')
706
            if len(status) > 1:
707
                self.object.patient.last_state = status[1]
708
                self.object.patient.save()
709
            else:
710
                # TODO return an error here
711
                return HttpResponseRedirect(self.get_success_url())
712
        self.object.delete()
713
        return HttpResponseRedirect(self.get_success_url())
714

    
715

    
716
update_patient_state = \
717
    UpdatePatientStateView.as_view(model=FileState,
718
        template_name = 'dossiers/generic_form.html',
719
        success_url = '../../view#tab=0',
720
        form_class=forms.PatientStateForm)
721
delete_patient_state = \
722
    DeletePatientView.as_view(model=FileState,
723
        template_name = 'dossiers/generic_confirm_delete.html',
724
        success_url = '../../view#tab=0')
725

    
726

    
727
class GenerateRtfFormView(cbv.FormView):
728
    template_name = 'dossiers/generate_rtf_form.html'
729
    form_class = forms.GenerateRtfForm
730
    success_url = './view#tab=0'
731

    
732
    def get_context_data(self, **kwargs):
733
        ctx = super(GenerateRtfFormView, self).get_context_data(**kwargs)
734
        ctx['object'] = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
735
        ctx['service_id'] = self.service.id
736
        if self.request.GET.get('event-id'):
737
            date = self.request.GET.get('date')
738
            date = datetime.strptime(date, '%Y-%m-%d').date()
739
            appointment = Appointment()
740
            event = EventWithAct.objects.get(id=self.request.GET.get('event-id'))
741
            event = event.today_occurrence(date)
742
            appointment.init_from_event(event, self.service)
743
            ctx['appointment'] = appointment
744
        return ctx
745

    
746
    def form_valid(self, form, **kwargs):
747
        ctx = self.get_context_data(**kwargs)
748
        patient = ctx['object']
749
        appointment = ctx['appointment']
750
        template_filename = form.cleaned_data.get('template_filename')
751
        dest_filename = datetime.now().strftime('%Y-%m-%d--%H:%M:%S') + '--' + template_filename
752
        from_path = os.path.join(settings.RTF_TEMPLATES_DIRECTORY, template_filename)
753
        to_path = ''
754
        persistent = True
755
        if settings.USE_PATIENT_FILE_RTF_REPOSITORY_DIRECTORY \
756
                or settings.RTF_REPOSITORY_DIRECTORY:
757
            if settings.USE_PATIENT_FILE_RTF_REPOSITORY_DIRECTORY:
758
                to_path = patient.get_ondisk_directory(self.service.name)
759
            if settings.RTF_REPOSITORY_DIRECTORY:
760
                to_path = os.path.join(to_path,
761
                    settings.RTF_REPOSITORY_DIRECTORY)
762
            to_path = os.path.join(to_path, dest_filename)
763
        else:
764
            # else : use temporary files
765
            persistent = False
766
            to_path = dest_filename
767
        variables = {'AD11': '', 'AD12': '', 'AD13': '', 'AD14': '',
768
            'AD15': '', 'AD18': '',
769
            'JOU1': formats.date_format(datetime.today(), "DATE_FORMAT"),
770
            'VIL1': u'Saint-Étienne',
771
            'RDV1': '', 'HEU1': '', 'THE1': '', 'DPA1': '',
772
            'NOM1': '', 'PRE1': '', 'NAI1': '', 'NUM2': '',
773
            'NOM2': '', 'PRE2': '', 'TPA1': '', 'NSS1': '',
774
            'TR01': '', 'TR02': '', 'TR03': '', 'TR04': '', 'TR05': '',
775
            'AD16': '', 'AD17': '', 'AD19': '',
776
            'AD21': '', 'AD22': '', 'AD23': '', 'AD24': '', 'AD25': '',
777
            'AD26': '', 'AD27': '', 'AD28': '', 'AD29': '',
778
            'RDV2': '' ,
779
        }
780
        list_rdvs = []
781
        for act in Act.objects.last_acts(patient):
782
            state = act.get_state()
783
            if state and state.state_name in ('VALIDE', 'ACT_DOUBLE'):
784
                rdv = "\t- %s" % formats.date_format(act.date, "DATE_FORMAT")
785
                if act.time:
786
                    rdv += " à %s" % formats.date_format(act.time, "TIME_FORMAT")
787
                list_rdvs.append(rdv)
788
        variables['RDV2'] = '\par'.join(list_rdvs)
789
        if appointment:
790
            variables['RDV1'] = appointment.date
791
            variables['HEU1'] = appointment.begin_hour
792
            variables['THE1'] = ' '.join([str(i) for i in appointment.workers])# ou DPA1?
793
            variables['DPA1'] = variables['THE1']
794
        if patient:
795
            variables['NOM1'] = patient.last_name
796
            variables['PRE1'] = patient.first_name
797
            if patient.birthdate :
798
                variables['NAI1'] = patient.birthdate.strftime('%d/%m/%Y')
799
            variables['NUM2'] = patient.paper_id
800
            if patient.policyholder:
801
                variables['NOM2'] = patient.policyholder.last_name
802
                variables['PRE2'] = patient.policyholder.first_name
803
                if patient.policyholder.health_center:
804
                    variables['TPA1'] = patient.policyholder.health_center.name
805
                if patient.policyholder.social_security_id:
806
                    key = str(patient.policyholder.get_control_key())
807
                    if len(key) == 1:
808
                        key = '0' + key
809
                    variables['NSS1'] = \
810
                        ' '.join([patient.policyholder.social_security_id,
811
                            key])
812
            if patient.transportcompany:
813
                variables['TR01'] = patient.transportcompany.name
814
                variables['TR02'] = patient.transportcompany.address
815
                variables['TR03'] = patient.transportcompany.address_complement
816
                variables['TR04'] = patient.transportcompany.zip_code
817
                variables['TR05'] = patient.transportcompany.city
818
        variables['AD18'] = form.cleaned_data.get('phone_address') or ''
819
        for i, line in enumerate(form.cleaned_data.get('address').splitlines()):
820
            variables['AD%d' % (11+i)] = line
821
            if i == 4:
822
                break
823

    
824
        filename = make_doc_from_template(from_path, to_path, variables,
825
            persistent)
826

    
827
        client_dir = patient.get_client_side_directory(self.service.name)
828
        if not client_dir:
829
            content = File(file(filename))
830
            response = HttpResponse(content,'text/rtf')
831
            response['Content-Length'] = content.size
832
            response['Content-Disposition'] = 'attachment; filename="%s"' \
833
                % dest_filename.encode('utf-8')
834
            return response
835
        else:
836
            class LocalFileHttpResponseRedirect(HttpResponseRedirect):
837
                allowed_schemes = ['file']
838
            client_filepath = os.path.join(client_dir, dest_filename)
839
            return LocalFileHttpResponseRedirect('file://' + client_filepath)
840

    
841
generate_rtf_form = GenerateRtfFormView.as_view()
842

    
843

    
844
class PatientRecordsQuotationsView(cbv.ListView):
845
    model = PatientRecord
846
    template_name = 'dossiers/quotations.html'
847

    
848
    def _get_search_result(self, paginate_patient_records):
849
        patient_records = []
850
        for patient_record in paginate_patient_records:
851
            current_state = patient_record.get_current_state()
852
            state = current_state.status.name
853
            state_class = current_state.status.type.lower()
854
            patient_records.append(
855
                    {
856
                        'object': patient_record,
857
                        'state': state,
858
                        'state_class': state_class
859
                        }
860
                    )
861
        return patient_records
862

    
863
    def get_queryset(self):
864
        form = forms.QuotationsForm(data=self.request.GET or None)
865
        qs = super(PatientRecordsQuotationsView, self).get_queryset()
866
        without_quotations = self.request.GET.get('without_quotations')
867
        if without_quotations:
868
            qs = qs.filter(mises_1=None).filter(mises_2=None).filter(mises_3=None)
869
        states = self.request.GET.getlist('states')
870
        qs = qs.filter(last_state__status__id__in=states)
871

    
872
        try:
873
            date_actes_start = datetime.strptime(form.data['date_actes_start'], "%d/%m/%Y")
874
            qs = qs.filter(act__date__gte=date_actes_start.date()).distinct()
875
        except (ValueError, KeyError):
876
            pass
877
        try:
878
            date_actes_end = datetime.strptime(form.data['date_actes_end'], "%d/%m/%Y")
879
            qs = qs.filter(act__date__lte=date_actes_end.date()).distinct()
880
        except (ValueError, KeyError):
881
            pass
882
        qs = qs.filter(service=self.service).order_by('last_name').prefetch_related()
883
        return qs
884

    
885
    def get_context_data(self, **kwargs):
886
        ctx = super(PatientRecordsQuotationsView, self).get_context_data(**kwargs)
887
        ctx['search_form'] = forms.QuotationsForm(data=self.request.GET or None,
888
                service=self.service)
889
        patient_records = []
890
        page = self.request.GET.get('page')
891
        paginator = Paginator(ctx['object_list'].filter(), 50)
892
        try:
893
            paginate_patient_records = paginator.page(page)
894
        except PageNotAnInteger:
895
            paginate_patient_records = paginator.page(1)
896
        except EmptyPage:
897
            paginate_patient_records = paginator.page(paginator.num_pages)
898

    
899
        ctx['patient_records'] = self._get_search_result(paginate_patient_records)
900
        ctx['paginate_patient_records'] = paginate_patient_records
901

    
902
        query = self.request.GET.copy()
903
        if 'page' in query:
904
            del query['page']
905
        ctx['query'] = query.urlencode()
906

    
907
        return ctx
908

    
909
patientrecord_quotations = PatientRecordsQuotationsView.as_view()
910

    
911

    
912
class CreateDirectoryView(View, cbv.ServiceViewMixin):
913
    def post(self, request, *args, **kwargs):
914
        patient = PatientRecord.objects.get(id=kwargs['patientrecord_id'])
915
        service = Service.objects.get(slug=kwargs['service'])
916
        patient.get_ondisk_directory(service.name)
917
        messages.add_message(self.request, messages.INFO, u'Répertoire patient créé.')
918
        return HttpResponseRedirect('view')
919

    
920
create_directory = CreateDirectoryView.as_view()
921

    
922
class GenerateTransportPrescriptionFormView(cbv.FormView):
923
    template_name = 'dossiers/generate_transport_prescription_form.html'
924
    form_class = Form
925
    success_url = './view#tab=1'
926

    
927
    def get_context_data(self, **kwargs):
928
        ctx = super(GenerateTransportPrescriptionFormView, self).get_context_data(**kwargs)
929
        ctx['lieu'] = 'Saint-Etienne'
930
        ctx['date'] = formats.date_format(datetime.today(), "SHORT_DATE_FORMAT")
931
        ctx['id_etab'] = '''%s SAINT ETIENNE
932
66/68, RUE MARENGO
933
42000 SAINT ETIENNE''' % ctx['service'].upper()
934
        try:
935
            patient = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
936
            ctx['object'] = patient
937
            last_log = TransportPrescriptionLog.objects.filter(patient=patient).latest('created')
938
            if last_log:
939
                ctx['choices'] = last_log.get_choices()
940
                if 'lieu' in ctx['choices'] and ctx['choices']['lieu']:
941
                    ctx['lieu'] = ctx['choices']['lieu']
942
                if 'date' in ctx['choices'] and ctx['choices']['date']:
943
                    ctx['date'] = ctx['choices']['date']
944
                if 'id_etab' in ctx['choices'] and ctx['choices']['id_etab']:
945
                    ctx['id_etab'] = ctx['choices']['id_etab']
946
        except:
947
            pass
948
        return ctx
949

    
950
    def form_valid(self, form):
951
        patient = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
952
        address = PatientAddress.objects.get(id=form.data['address_id'])
953
        path = render_transport(patient, address, form.data)
954
        content = File(file(path))
955
        log = TransportPrescriptionLog(patient=patient)
956
        log.set_choices(form.data)
957
        log.save()
958
        response = HttpResponse(content,'application/pdf')
959
        response['Content-Length'] = content.size
960
        dest_filename = "%s--prescription-transport-%s-%s.pdf" \
961
            % (datetime.now().strftime('%Y-%m-%d--%H:%M:%S'),
962
            patient.last_name.upper().encode('utf-8'),
963
            patient.first_name.encode('utf-8'))
964
        response['Content-Disposition'] = \
965
            'attachment; filename="%s"' % dest_filename
966
        return response
967

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