Project

General

Profile

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

calebasse / calebasse / dossiers / views.py @ 0bb70851

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

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

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

    
462
    def form_valid(self, form):
463
        messages.add_message(self.request, messages.INFO, u'Modification enregistrée avec succès.')
464
        return super(PatientRecordView, self).form_valid(form)
465

    
466

    
467
patient_record = PatientRecordView.as_view()
468

    
469
class PatientRecordsHomepageView(cbv.ListView):
470
    model = PatientRecord
471
    template_name = 'dossiers/index.html'
472

    
473

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

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

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

    
532
        page = self.request.GET.get('page')
533
        if ctx['object_list']:
534
            patient_records = ctx['object_list'].filter()
535
        else:
536
            patient_records = []
537

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

    
552
        query = self.request.GET.copy()
553
        if 'page' in query:
554
            del query['page']
555
        ctx['query'] = query.urlencode()
556

    
557
        ctx['paginate_patient_records'] = paginate_patient_records
558
        ctx['patient_records'] = self._get_search_result(paginate_patient_records)
559
        return ctx
560

    
561
patientrecord_home = PatientRecordsHomepageView.as_view()
562

    
563
class PatientRecordDeleteView(DeleteView):
564
    model = PatientRecord
565
    success_url = ".."
566
    template_name = 'dossiers/patientrecord_confirm_delete.html'
567

    
568
patientrecord_delete = validator_only(PatientRecordDeleteView.as_view())
569

    
570

    
571
class PatientRecordPaperIDUpdateView(cbv.UpdateView):
572
    model = PatientRecord
573
    form_class = forms.PaperIDForm
574
    template_name = 'dossiers/generic_form.html'
575
    success_url = '../..'
576

    
577
update_paper_id = PatientRecordPaperIDUpdateView.as_view()
578

    
579

    
580
class NewSocialisationDurationView(cbv.CreateView):
581
    model = SocialisationDuration
582
    form_class = forms.SocialisationDurationForm
583
    template_name = 'dossiers/generic_form.html'
584
    success_url = '../view#tab=6'
585

    
586
    def get_success_url(self):
587
        return self.success_url
588

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

    
594
    def form_valid(self, form):
595
        duration = form.save()
596
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
597
        patientrecord.socialisation_durations.add(duration)
598
        return HttpResponseRedirect(self.get_success_url())
599

    
600
new_socialisation_duration = NewSocialisationDurationView.as_view()
601

    
602
class UpdateSocialisationDurationView(cbv.UpdateView):
603
    model = SocialisationDuration
604
    form_class = forms.SocialisationDurationForm
605
    template_name = 'dossiers/generic_form.html'
606
    success_url = '../../view#tab=6'
607

    
608
    def get(self, request, *args, **kwargs):
609
        if kwargs.has_key('patientrecord_id'):
610
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
611
        return super(UpdateSocialisationDurationView, self).get(request, *args, **kwargs)
612

    
613
update_socialisation_duration = UpdateSocialisationDurationView.as_view()
614

    
615
class DeleteSocialisationDurationView(cbv.DeleteView):
616
    model = SocialisationDuration
617
    form_class = forms.SocialisationDurationForm
618
    template_name = 'dossiers/socialisationduration_confirm_delete.html'
619
    success_url = '../../view#tab=6'
620

    
621
delete_socialisation_duration = DeleteSocialisationDurationView.as_view()
622

    
623

    
624
class NewMDPHRequestView(cbv.CreateView):
625
    def get(self, request, *args, **kwargs):
626
        if kwargs.has_key('patientrecord_id'):
627
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
628
        return super(NewMDPHRequestView, self).get(request, *args, **kwargs)
629

    
630
    def form_valid(self, form):
631
        request = form.save()
632
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
633
        patientrecord.mdph_requests.add(request)
634
        return HttpResponseRedirect(self.success_url)
635

    
636
class UpdateMDPHRequestView(cbv.UpdateView):
637
    def get(self, request, *args, **kwargs):
638
        if kwargs.has_key('patientrecord_id'):
639
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
640
        return super(UpdateMDPHRequestView, self).get(request, *args, **kwargs)
641

    
642

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

    
658
class NewMDPHResponseView(cbv.CreateView):
659
    def get(self, request, *args, **kwargs):
660
        if kwargs.has_key('patientrecord_id'):
661
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
662
        return super(NewMDPHResponseView, self).get(request, *args, **kwargs)
663

    
664
    def form_valid(self, form):
665
        response = form.save()
666
        patientrecord = PatientRecord.objects.get(id=self.kwargs['patientrecord_id'])
667
        patientrecord.mdph_responses.add(response)
668
        return HttpResponseRedirect(self.success_url)
669

    
670
class UpdateMDPHResponseView(cbv.UpdateView):
671
    def get(self, request, *args, **kwargs):
672
        if kwargs.has_key('patientrecord_id'):
673
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
674
        return super(UpdateMDPHResponseView, self).get(request, *args, **kwargs)
675

    
676

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

    
692

    
693
class UpdatePatientStateView(cbv.ServiceFormMixin, cbv.UpdateView):
694

    
695
    def get_initial(self):
696
        initial = super(UpdatePatientStateView, self).get_initial()
697
        initial['date_selected'] = self.object.date_selected.date()
698
        return initial
699

    
700
    def get(self, request, *args, **kwargs):
701
        if kwargs.has_key('patientrecord_id'):
702
            request.session['patientrecord_id'] = kwargs['patientrecord_id']
703
        return super(UpdatePatientStateView, self).get(request, *args, **kwargs)
704

    
705
class DeletePatientView(cbv.DeleteView):
706

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

    
720

    
721
update_patient_state = \
722
    UpdatePatientStateView.as_view(model=FileState,
723
        template_name = 'dossiers/generic_form.html',
724
        success_url = '../../view#tab=0',
725
        form_class=forms.PatientStateForm)
726
delete_patient_state = \
727
    DeletePatientView.as_view(model=FileState,
728
        template_name = 'dossiers/generic_confirm_delete.html',
729
        success_url = '../../view#tab=0')
730

    
731

    
732
class GenerateRtfFormView(cbv.FormView):
733
    template_name = 'dossiers/generate_rtf_form.html'
734
    form_class = forms.GenerateRtfForm
735
    success_url = './view#tab=0'
736

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

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

    
829
        filename = make_doc_from_template(from_path, to_path, variables,
830
            persistent)
831

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

    
846
generate_rtf_form = GenerateRtfFormView.as_view()
847

    
848

    
849
class PatientRecordsQuotationsView(cbv.ListView):
850
    model = PatientRecord
851
    template_name = 'dossiers/quotations.html'
852

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

    
868
    def get_queryset(self):
869
        form = forms.QuotationsForm(data=self.request.GET or None)
870
        qs = super(PatientRecordsQuotationsView, self).get_queryset()
871
        without_quotations = self.request.GET.get('without_quotations')
872
        if without_quotations:
873
            qs = qs.filter(mises_1=None).filter(mises_2=None).filter(mises_3=None)
874
        states = self.request.GET.getlist('states')
875
        qs = qs.filter(last_state__status__id__in=states)
876

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

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

    
904
        ctx['patient_records'] = self._get_search_result(paginate_patient_records)
905
        ctx['paginate_patient_records'] = paginate_patient_records
906

    
907
        query = self.request.GET.copy()
908
        if 'page' in query:
909
            del query['page']
910
        ctx['query'] = query.urlencode()
911

    
912
        return ctx
913

    
914
patientrecord_quotations = PatientRecordsQuotationsView.as_view()
915

    
916

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

    
925
create_directory = CreateDirectoryView.as_view()
926

    
927
class GenerateTransportPrescriptionFormView(cbv.FormView):
928
    template_name = 'dossiers/generate_transport_prescription_form.html'
929
    form_class = Form
930
    success_url = './view#tab=1'
931

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

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

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