Project

General

Profile

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

calebasse / calebasse / statistics / statistics.py @ afdbbe7a

1
# -*- coding: utf-8 -*-
2
import os
3
import tempfile
4
import csv
5

    
6
from collections import OrderedDict
7
from datetime import datetime, timedelta
8
from dateutil.relativedelta import relativedelta
9

    
10
from django.db import models
11
from django.db.models import Count
12
from django.utils import formats
13
from django.conf import settings
14

    
15
from calebasse.dossiers.models import PatientRecord, FileState
16
from calebasse.personnes.models import Worker
17
from calebasse.actes.models import Act
18
from calebasse.agenda.models import Event
19

    
20

    
21
STATISTICS = {
22
    'patients_per_worker_for_period' :
23
        {
24
        'display_name': 'Enfants suivis par intervenant sur une période',
25
        'category': 'Patients',
26
        'comment': """Liste et décompte des patients par intervenant pour les
27
            patients ayant eu au moins un acte proposé avec cet intervenant
28
            sur la plage de dates spécifiée. La date de début de la plage par
29
            défaut est le 1er janvier de l'année en cours. La date de fin de
30
            la plage par défaut est aujourd'hui. Si aucun patient ou
31
            intervenant n'est spécifié, tous les patients et les intervenants
32
            sont pris en compte. A l'inverse, si des patients ou des
33
            intervenants sont indiqués, seuls ceux-ci sont pris en compte.
34
            """
35
    },
36
    'active_patients_by_state_only' :
37
        {
38
        'display_name': "Dossiers actifs selon l'état du dossier à une date donnée",
39
        'category': 'Patients',
40
        'comment': """Listes des patients dont le dossier était actif à une date donnée.
41
            Rappel des états actifs des dossiers : CMPP : diagnostic
42
            ou traitement, CAMSP : suivi, SESSAD: Traitement.
43
            La date par défaut est aujourd'hui.
44
            """
45
    },
46
    'active_patients_with_act' :
47
        {
48
        'display_name': 'Dossiers actifs et inactifs avec un acte validé ou non sur une période',
49
        'category': 'Patients',
50
        'comment': """Listes des patients ayant eu au moins un acte proposé
51
            durant la période indiquée. Les patients sont scindés en quatre
52
            tableaux.
53
            Les patients dont au moins un acte a été
54
            validé ET dont le dossier est dans un état "actif".
55
            Les patients dont au moins un acte a été
56
            validé ET dont le dossier N'est PAS dans un état "actif".
57
            Les patients sans aucun acte validé ET dont le dossier est dans
58
            un état "actif".
59
            Les patients sans aucun acte validé ET dont le dossier N'est PAS
60
            dans un état "actif".
61
            Rappel des états actifs des dossiers : CMPP : diagnostic
62
            ou traitement, CAMSP : suivi, SESSAD: Traitement.
63
            La date de début de la plage par
64
            défaut est le 1er janvier de l'année en cours. La date de fin de
65
            la plage par défaut est aujourd'hui.
66
            """
67
    },
68
    'closed_files' :
69
        {
70
        'display_name': 'Dossier clos sur une période et durée de la prise '
71
            'en charge',
72
        'category': 'Patients',
73
        'comment': """Liste des dossiers clos avec leur durée de la prise en
74
            charge sur la plage de dates spécifiée. Le nombre de dossier et la
75
            durée moyenne de la prise en charge est également donnée. La date
76
            de début de la plage par défaut est le 1er janvier de l'année en
77
            cours. La date de fin de la plage par défaut est aujourd'hui.
78
            """
79
    },
80
    'annual_activity' :
81
        {
82
        'display_name': "Activité annuelle",
83
        'category': 'Intervenants',
84
        'comment': """Tableaux de synthèse annuelle. La date saisie
85
            indique l'année à traiter. Si aucune date n'est spécifiée ce sera
86
            l'année en cours. Si aucun intervenant n'est spécifié, les
87
            tableaux de synthèse globaux sont retournés. Si des intervenants
88
            sont indiqués, les tableaux de synthèse pour chaque intervenant
89
            sont retournés.
90
            """
91
    },
92
    'patients_details' :
93
        {
94
        'display_name': "Synthèse par patient",
95
        'category': 'Patients',
96
        'comment': """Tableaux de synthèse par patient. Si aucun patient n'est
97
            indiqué, une synthèse pour chaque patient est retournée. La plage
98
            de date permet de selectionner les patients pour lesquels au
99
            moins au acte a été proposé durant cette période. Si un dossier a
100
            été clos durant cette période mais qu'aucun acte n'a été proposé
101
            durant cette période, il ne sera pas pris en compte. La date de
102
            début de la plage par défaut est le 1er janvier de l'année en
103
            cours. La date de fin de la plage par défaut est aujourd'hui. """
104
    },
105
    'patients_synthesis' :
106
        {
107
        'display_name': 'Synthèse sur les patients avec un acte valide sur '
108
            'la plage de date',
109
        'category': 'Patients',
110
        'comment': """Patients ayant eu au moins un acte validé
111
            sur la plage de dates spécifiée. La date de début de la plage par
112
            défaut est le 1er janvier de l'année en cours. La date de fin de
113
            la plage par défaut est aujourd'hui.
114
            """
115
    },
116
    'acts_synthesis' :
117
        {
118
        'display_name': 'Synthèse sur les actes',
119
        'category': 'Actes',
120
        'comment': """Synthèse sur les actes
121
            sur la plage de dates spécifiée. La date de début de la plage par
122
            défaut est le 1er janvier de l'année en cours. La date de fin de
123
            la plage par défaut est aujourd'hui.
124
            """
125
    },
126
    'acts_synthesis_cmpp' :
127
        {
128
        'display_name': 'Synthèse sur les dossiers facturés au CMPP',
129
        'category': 'Patients',
130
        'services': ['CMPP', ],
131
        'comment': """Synthèse sur les dossiers facturés au CMPP selon que ce
132
            soit en diagnostic, en traitement ou les deux,
133
            sur la plage de dates spécifiée. La date de début de la plage par
134
            défaut est le 1er janvier de l'année en cours. La date de fin de
135
            la plage par défaut est aujourd'hui.
136
            """
137
    },
138
    'mises' :
139
        {
140
        'display_name': 'Synthèse sur les pathologies MISES',
141
        'category': 'Patients',
142
        'comment': """Synthèse sur les pathologies
143
            sur la plage de dates spécifiée. La date de début de la plage par
144
            défaut est le 1er janvier de l'année en cours. La date de fin de
145
            la plage par défaut est aujourd'hui.
146
            """
147
    },
148
    'deficiencies' :
149
        {
150
        'display_name': 'Synthèse sur les déficiences',
151
        'category': 'Patients',
152
        'comment': """Synthèse sur les déficiences
153
            sur la plage de dates spécifiée. La date de début de la plage par
154
            défaut est le 1er janvier de l'année en cours. La date de fin de
155
            la plage par défaut est aujourd'hui.
156
            """
157
    },
158
    'patients_protection' :
159
        {
160
        'display_name': 'Synthèse sur les mesures de protection des patients '
161
            'à une date donnée',
162
        'category': 'Patients',
163
        'comment': """La date par défaut est aujourd'hui.
164
            """
165
    },
166
}
167

    
168
ANNUAL_ACTIVITY_ROWS = ['total', 'pointe', 'non_pointe', 'absent', 'percent_abs', 'reporte', 'acts_present', 'abs_non_exc', 'abs_exc', 'abs_inter', 'annul_nous', 'annul_famille', 'abs_ess_pps', 'enf_hosp', 'non_facturables', 'facturables', 'perdus', 'doubles', 'really_facturables', 'factures', 'diag', 'trait', 'restants_a_fac', 'refac', 'nf', 'percent_nf', 'patients', 'intervenants', 'days', 'fact_per_day', 'moving_time', 'moving_time_per_intervene', 'moving_time_per_act']
169

    
170
ANNUAL_ACTIVITY_COLUMN_LABELS = ['Janv', 'Fév', 'Mar', 'T1', 'Avr', 'Mai', 'Jui', 'T2', 'Jui', 'Aoû', 'Sep', 'T3', 'Oct', 'Nov', 'Déc', 'T4', 'Total']
171

    
172
class AnnualActivityProcessingColumn():
173
    total = 0
174
    pointe = 0
175
    non_pointe = 0
176
    absent = 0
177
    percent_abs = 0
178
    reporte = 0
179
    acts_present = 0
180
    abs_non_exc = 0
181
    abs_exc = 0
182
    abs_inter = 0
183
    annul_nous = 0
184
    annul_famille = 0
185
    abs_ess_pps = 0
186
    enf_hosp = 0
187
    non_facturables = 0
188
    facturables = 0
189
    perdus = 0
190
    doubles = 0
191
    really_facturables = 0
192
    factures = 0
193
    diag = 0
194
    trait = 0
195
    restants_a_fac = 0
196
    refac = 0
197
    nf = 0
198
    percent_nf = 0
199
    patients = 0
200
    intervenants = 0
201
    days = 0
202
    fact_per_day = 0
203
    moving_time = timedelta()
204
    moving_time_per_intervene = timedelta()
205
    moving_time_per_act = timedelta()
206

    
207
def annual_activity_month_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant=None):
208
    rd = relativedelta(months=1)
209
    sd = start_day + i * rd
210
    ed = sd + rd
211
    acts = None
212
    moving_events = None
213
    if participant:
214
        acts = Act.objects.filter(date__gte=sd.date(),
215
            date__lt=ed.date(), patient__service=statistic.in_service,
216
            doctors__in=[participant])
217
        moving_events = Event.objects.filter(event_type__label='Temps de trajet',
218
            start_datetime__gte=sd, end_datetime__lt=ed,
219
            services__in=[statistic.in_service],
220
            participants__in=[participant])
221
    else:
222
        acts = Act.objects.filter(date__gte=sd.date(),
223
            date__lt=ed.date(), patient__service=statistic.in_service)
224
        moving_events = Event.objects.filter(event_type__label='Temps de trajet',
225
            start_datetime__gte=sd, end_datetime__lt=ed,
226
            services__in=[statistic.in_service])
227
    analyses[key].append(AnnualActivityProcessingColumn())
228
    analyses[key][i+trim_cnt].patients = acts.aggregate(Count('patient', distinct=True))['patient__count']
229
    analyses[key][i+trim_cnt].intervenants = acts.aggregate(Count('doctors', distinct=True))['doctors__count']
230
    analyses[key][i+trim_cnt].days = acts.aggregate(Count('date', distinct=True))['date__count']
231
    for me in moving_events:
232
        analyses[key][i+trim_cnt].moving_time += me.timedelta()
233
    for a in acts:
234
        if a.is_new():
235
            analyses[key][i+trim_cnt].non_pointe += 1
236
        elif a.is_absent():
237
            state = a.get_state()
238
            if state.state_name == 'REPORTE':
239
                analyses[key][i+trim_cnt].reporte += 1
240
            else:
241
                analyses[key][i+trim_cnt].absent += 1
242
                if state.state_name == 'ABS_NON_EXC':
243
                    analyses[key][i+trim_cnt].abs_non_exc += 1
244
                elif state.state_name == 'ABS_EXC':
245
                    analyses[key][i+trim_cnt].abs_exc += 1
246
                elif state.state_name == 'ABS_INTER':
247
                    analyses[key][i+trim_cnt].abs_inter += 1
248
                elif state.state_name == 'ANNUL_NOUS':
249
                    analyses[key][i+trim_cnt].annul_nous += 1
250
                elif state.state_name == 'ANNUL_FAMILLE':
251
                    analyses[key][i+trim_cnt].annul_famille += 1
252
                elif state.state_name == 'ABS_ESS_PPS':
253
                    analyses[key][i+trim_cnt].abs_ess_pps += 1
254
                elif state.state_name == 'ENF_HOSP':
255
                    analyses[key][i+trim_cnt].enf_hosp += 1
256
        else:
257
            analyses[key][i+trim_cnt].acts_present += 1
258
            if statistic.in_service.name == 'CMPP':
259
                if not a.is_billable():
260
                    analyses[key][i+trim_cnt].non_facturables += 1
261
                elif a.is_lost:
262
                    analyses[key][i+trim_cnt].perdus += 1
263
                elif a.get_state().state_name == 'ACT_DOUBLE':
264
                    analyses[key][i+trim_cnt].doubles += 1
265
                elif a.is_billed:
266
                    analyses[key][i+trim_cnt].factures += 1
267
                    if a.invoice_set.latest('created').first_tag[0] == 'D':
268
                        analyses[key][i+trim_cnt].diag += 1
269
                    else:
270
                        analyses[key][i+trim_cnt].trait += 1
271
                else:
272
                    analyses[key][i+trim_cnt].restants_a_fac += 1
273
                    if a.invoice_set.all():
274
                        analyses[key][i+trim_cnt].refac += 1
275

    
276
    analyses[key][i+trim_cnt].total = analyses[key][i+trim_cnt].non_pointe + analyses[key][i+trim_cnt].reporte + analyses[key][i+trim_cnt].absent + analyses[key][i+trim_cnt].acts_present
277
    analyses[key][i+trim_cnt].pointe = analyses[key][i+trim_cnt].total - analyses[key][i+trim_cnt].non_pointe
278
    percent_abs = 100
279
    if not analyses[key][i+trim_cnt].pointe or not analyses[key][i+trim_cnt].absent:
280
        percent_abs = 0
281
    elif analyses[key][i+trim_cnt].absent:
282
        percent_abs = (analyses[key][i+trim_cnt].absent/float(analyses[key][i+trim_cnt].pointe))*100
283
    analyses[key][i+trim_cnt].percent_abs = "%.2f" % percent_abs
284

    
285
    if statistic.in_service.name == 'CMPP':
286
        analyses[key][i+trim_cnt].facturables = analyses[key][i+trim_cnt].acts_present - analyses[key][i+trim_cnt].non_facturables
287
        analyses[key][i+trim_cnt].really_facturables = analyses[key][i+trim_cnt].facturables - analyses[key][i+trim_cnt].perdus - analyses[key][i+trim_cnt].doubles
288
        analyses[key][i+trim_cnt].nf = analyses[key][i+trim_cnt].perdus + analyses[key][i+trim_cnt].doubles + analyses[key][i+trim_cnt].non_facturables # + analyses[key][i+trim_cnt].reporte
289
        percent_nf = 100
290
        if not analyses[key][i+trim_cnt].pointe or not analyses[key][i+trim_cnt].nf:
291
            percent_nf = 0
292
        elif analyses[key][i+trim_cnt].nf:
293
            percent_nf = (analyses[key][i+trim_cnt].nf/float(analyses[key][i+trim_cnt].pointe))*100
294
        analyses[key][i+trim_cnt].percent_nf = "%.2f" % percent_nf
295
        if analyses[key][i+trim_cnt].days:
296
            analyses[key][i+trim_cnt].fact_per_day = "%.2f" % (analyses[key][i+trim_cnt].really_facturables / float(analyses[key][i+trim_cnt].days))
297

    
298
    if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].intervenants:
299
        analyses[key][i+trim_cnt].moving_time_per_intervene = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].intervenants
300
    if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].acts_present:
301
        analyses[key][i+trim_cnt].moving_time_per_act = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].acts_present
302

    
303

    
304
def annual_activity_trimester_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant=None):
305
    analyses[key].append(AnnualActivityProcessingColumn())
306
    rd = relativedelta(months=1)
307
    sd = start_day + i * rd
308
    start = start_day + (i-2) * rd
309
    end = sd + rd
310
    acts = None
311
    if participant:
312
        acts = Act.objects.filter(date__gte=start.date(),
313
            date__lt=end.date(), patient__service=statistic.in_service,
314
            doctors__in=[participant])
315
    else:
316
        acts = Act.objects.filter(date__gte=start.date(),
317
            date__lt=end.date(), patient__service=statistic.in_service)
318
    for row in ANNUAL_ACTIVITY_ROWS:
319
        if row == 'percent_abs':
320
            pointe = analyses[key][i+trim_cnt-1].pointe + analyses[key][i-2+trim_cnt].pointe + analyses[key][i-3+trim_cnt].pointe
321
            tot_abs = analyses[key][i+trim_cnt-1].absent + analyses[key][i-2+trim_cnt].absent + analyses[key][i-3+trim_cnt].absent
322
            percent_abs = 100
323
            if not pointe or not tot_abs:
324
                percent_abs = 0
325
            elif tot_abs:
326
                percent_abs = (tot_abs/float(pointe))*100
327
            analyses[key][i+trim_cnt].percent_abs = "%.2f" % percent_abs
328
        elif row == 'percent_nf':
329
            pointe = analyses[key][i+trim_cnt-1].pointe + analyses[key][i-2+trim_cnt].pointe + analyses[key][i-3+trim_cnt].pointe
330
            tot_nf = analyses[key][i+trim_cnt-1].nf + analyses[key][i-2+trim_cnt].nf + analyses[key][i-3+trim_cnt].nf
331
            percent_nf = 100
332
            if not pointe or not tot_nf:
333
                percent_nf = 0
334
            elif tot_nf:
335
                percent_nf = (tot_nf/float(pointe))*100
336
            analyses[key][i+trim_cnt].percent_nf = "%.2f" % percent_nf
337
        elif row == 'patients':
338
            analyses[key][i+trim_cnt].patients = acts.aggregate(Count('patient', distinct=True))['patient__count']
339
        elif row == 'intervenants':
340
            analyses[key][i+trim_cnt].intervenants = acts.aggregate(Count('doctors', distinct=True))['doctors__count']
341
        elif row == 'fact_per_day':
342
            if analyses[key][i+trim_cnt].days:
343
                analyses[key][i+trim_cnt].fact_per_day = "%.2f" % (analyses[key][i+trim_cnt].really_facturables / float(analyses[key][i+trim_cnt].days))
344
        elif row == 'moving_time_per_intervene':
345
            if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].intervenants:
346
                analyses[key][i+trim_cnt].moving_time_per_intervene = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].intervenants
347
        elif row == 'moving_time_per_act':
348
            if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].acts_present:
349
                analyses[key][i+trim_cnt].moving_time_per_act = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].acts_present
350
        else:
351
            setattr(analyses[key][i+trim_cnt], row, getattr(analyses[key][i+trim_cnt-1], row) + getattr(analyses[key][i-2+trim_cnt], row) + getattr(analyses[key][i-3+trim_cnt], row))
352

    
353
def annual_activity_synthesis_analysis(statistic, start_day, end_day, analyses, key, participant=None):
354
    analyses[key].append(AnnualActivityProcessingColumn())
355
    acts = None
356
    if participant:
357
        acts = Act.objects.filter(date__gte=start_day.date(),
358
            date__lt=end_day.date(), patient__service=statistic.in_service,
359
            doctors__in=[participant])
360
    else:
361
        acts = Act.objects.filter(date__gte=start_day.date(),
362
            date__lt=end_day.date(), patient__service=statistic.in_service)
363
    for row in ANNUAL_ACTIVITY_ROWS:
364
        if row == 'percent_abs':
365
            tot_abs = 0
366
            pointe = 0
367
            for i in (3, 7, 11, 15):
368
                pointe += analyses[key][i].pointe
369
                tot_abs += analyses[key][i].absent
370
            percent_abs = 100
371
            if not pointe or not tot_abs:
372
                percent_abs = 0
373
            elif tot_abs:
374
                percent_abs = (tot_abs/float(pointe))*100
375
            analyses[key][16].percent_abs = "%.2f" % percent_abs
376
        elif row == 'percent_nf':
377
            tot_nf= 0
378
            pointe = 0
379
            for i in (3, 7, 11, 15):
380
                pointe += analyses[key][i].pointe
381
                tot_nf += analyses[key][i].nf
382
            percent_nf = 100
383
            if not pointe or not tot_nf:
384
                percent_nf = 0
385
            elif tot_nf:
386
                percent_nf = (tot_nf/float(pointe))*100
387
            analyses[key][16].percent_nf = "%.2f" % percent_nf
388
        elif row == 'patients':
389
            analyses[key][16].patients = acts.aggregate(Count('patient', distinct=True))['patient__count']
390
        elif row == 'intervenants':
391
            analyses[key][16].intervenants = acts.aggregate(Count('doctors', distinct=True))['doctors__count']
392
        elif row == 'fact_per_day':
393
            if analyses[key][16].days:
394
                analyses[key][16].fact_per_day = "%.2f" % (analyses[key][16].really_facturables / float(analyses[key][16].days))
395
        elif row == 'moving_time_per_intervene':
396
            if analyses[key][16].moving_time and analyses[key][16].intervenants:
397
                analyses[key][16].moving_time_per_intervene = analyses[key][16].moving_time / analyses[key][16].intervenants
398
        elif row == 'moving_time_per_act':
399
            if analyses[key][16].moving_time and analyses[key][16].acts_present:
400
                analyses[key][16].moving_time_per_act = analyses[key][16].moving_time / analyses[key][16].acts_present
401
        else:
402
            val = 0
403
            if row == 'moving_time':
404
                val = timedelta()
405
            for i in (3, 7, 11, 15):
406
                val += getattr(analyses[key][i], row)
407
            setattr(analyses[key][16], row, val)
408

    
409
def strfdelta(tdelta, fmt):
410
    if not tdelta:
411
        return '0'
412
    d = {"days": tdelta.days}
413
    d["hours"], rem = divmod(tdelta.seconds, 3600)
414
    d["minutes"], d["seconds"] = divmod(rem, 60)
415
    return fmt.format(**d)
416

    
417
def annual_activity_build_tables(statistic, analyses, key, label, data_tables):
418
    table_1 = []
419
    table_1_label = label + ' - général'
420
    table_1.append([table_1_label] + ANNUAL_ACTIVITY_COLUMN_LABELS)
421
    rows = []
422
    row = ['Proposés']
423
    for column in analyses[key]:
424
        row.append(column.total)
425
    rows.append(row)
426
    row = ['Non pointés']
427
    for column in analyses[key]:
428
        row.append(column.non_pointe)
429
    rows.append(row)
430
    row = ['Absences']
431
    for column in analyses[key]:
432
        row.append(column.absent)
433
    rows.append(row)
434
    row = ['Reportés']
435
    for column in analyses[key]:
436
        row.append(column.reporte)
437
    rows.append(row)
438
    row = ['Présents']
439
    for column in analyses[key]:
440
        row.append(column.acts_present)
441
    rows.append(row)
442
    if statistic.in_service.name == 'CMPP':
443
        row = ['Facturables']
444
        for column in analyses[key]:
445
            row.append(column.really_facturables)
446
        rows.append(row)
447
        row = ['Facturés']
448
        for column in analyses[key]:
449
            row.append(column.factures)
450
        rows.append(row)
451
        row = ['Diagnostics']
452
        for column in analyses[key]:
453
            row.append(column.diag)
454
        rows.append(row)
455
        row = ['Traitements']
456
        for column in analyses[key]:
457
            row.append(column.trait)
458
        rows.append(row)
459
        row = ['Restants à facturer']
460
        for column in analyses[key]:
461
            row.append(column.restants_a_fac)
462
        rows.append(row)
463
        row = ['Dont en refact.']
464
        for column in analyses[key]:
465
            row.append(column.refac)
466
        rows.append(row)
467
    row = ['Patients']
468
    for column in analyses[key]:
469
        row.append(column.patients)
470
    rows.append(row)
471
    row = ['Intervenants']
472
    for column in analyses[key]:
473
        row.append(column.intervenants)
474
    rows.append(row)
475
    row = ['Jours']
476
    for column in analyses[key]:
477
        row.append(column.days)
478
    rows.append(row)
479
    if statistic.in_service.name == 'CMPP':
480
        row = ['Facturables / jour']
481
        for column in analyses[key]:
482
            row.append(column.fact_per_day)
483
        rows.append(row)
484
    row = ['Temps de déplacement']
485
    for column in analyses[key]:
486
        row.append(strfdelta(column.moving_time, "{hours}h {minutes}m"))
487
        if column.moving_time.days:
488
            row.append(strfdelta(column.moving_time, "{days}j {hours}h {minutes}m"))
489
    rows.append(row)
490
    row = ['Temps de déplacement par intervenant']
491
    for column in analyses[key]:
492
        row.append(strfdelta(column.moving_time_per_intervene, "{hours}h {minutes}m"))
493
        if column.moving_time_per_intervene.days:
494
            row.append(strfdelta(column.moving_time_per_intervene, "{days}j {hours}h {minutes}m"))
495
    rows.append(row)
496
    row = ['Temps de déplacement par acte']
497
    for column in analyses[key]:
498
        row.append(strfdelta(column.moving_time_per_act, "{hours}h {minutes}m"))
499
        if column.moving_time_per_act.days:
500
            row.append(strfdelta(column.moving_time_per_act, "{days}j {hours}h {minutes}m"))
501
    rows.append(row)
502
    table_1.append(rows)
503
    data_tables.append(table_1)
504

    
505
    table_2 = []
506
    table_2_label = label + ' - absences'
507
    table_2.append([table_2_label] + ANNUAL_ACTIVITY_COLUMN_LABELS)
508
    rows = []
509
    row = ['Pointés']
510
    for column in analyses[key]:
511
        row.append(column.pointe)
512
    rows.append(row)
513
    row = ['Absences']
514
    for column in analyses[key]:
515
        row.append(column.absent)
516
    rows.append(row)
517
    row = ['% absences / pointés']
518
    for column in analyses[key]:
519
        row.append(column.percent_abs)
520
    rows.append(row)
521
    row = ['Excusées']
522
    for column in analyses[key]:
523
        row.append(column.abs_exc)
524
    rows.append(row)
525
    row = ['Non excusées']
526
    for column in analyses[key]:
527
        row.append(column.abs_non_exc)
528
    rows.append(row)
529
    row = ["De l'intervenant"]
530
    for column in analyses[key]:
531
        row.append(column.abs_inter)
532
    rows.append(row)
533
    row = ["Annulés par nous"]
534
    for column in analyses[key]:
535
        row.append(column.annul_nous)
536
    rows.append(row)
537
    row = ['Annulés par la famille']
538
    for column in analyses[key]:
539
        row.append(column.annul_famille)
540
    rows.append(row)
541
    row = ['ESS PPS']
542
    for column in analyses[key]:
543
        row.append(column.abs_ess_pps)
544
    rows.append(row)
545
    row = ['Hospitalisations']
546
    for column in analyses[key]:
547
        row.append(column.enf_hosp)
548
    rows.append(row)
549
    table_2.append(rows)
550
    data_tables.append(table_2)
551

    
552
    if statistic.in_service.name == 'CMPP':
553
        table_3 = []
554
        table_3_label = label + ' - non fact.'
555
        table_3.append([table_3_label] + ANNUAL_ACTIVITY_COLUMN_LABELS)
556
        rows = []
557
        row = ['Pointés']
558
        for column in analyses[key]:
559
            row.append(column.pointe)
560
        rows.append(row)
561
        row = ['Présents']
562
        for column in analyses[key]:
563
            row.append(column.acts_present)
564
        rows.append(row)
565
        row = ['De type non fact.']
566
        for column in analyses[key]:
567
            row.append(column.non_facturables)
568
        rows.append(row)
569
        row = ['De type fact.']
570
        for column in analyses[key]:
571
            row.append(column.facturables)
572
        rows.append(row)
573
        row = ['Perdus']
574
        for column in analyses[key]:
575
            row.append(column.perdus)
576
        rows.append(row)
577
        row = ['En doubles']
578
        for column in analyses[key]:
579
            row.append(column.doubles)
580
        rows.append(row)
581
        row = ['Non facturables']
582
        for column in analyses[key]:
583
            row.append(column.nf)
584
        rows.append(row)
585
        row = ['% NF / pointés']
586
        for column in analyses[key]:
587
            row.append(column.percent_nf)
588
        rows.append(row)
589
        table_3.append(rows)
590
        data_tables.append(table_3)
591

    
592
def run_annual_activity(statistic, start_day, analyses, key, label, data_tables, participant=None):
593
    analyses[key] = list()
594
    trim_cnt = 0
595
    for i in range(0, 12):
596
        annual_activity_month_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant)
597
        if not (i + 1) % 3:
598
            trim_cnt += 1
599
            annual_activity_trimester_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant)
600
    end_day = datetime(start_day.year+1, 1, 1)
601
    annual_activity_synthesis_analysis(statistic, start_day, end_day, analyses, key, participant)
602
    annual_activity_build_tables(statistic, analyses, key, label, data_tables)
603

    
604
def annual_activity(statistic):
605
    if not statistic.in_service:
606
        return None
607
    start_day = datetime(datetime.today().year, 1, 1)
608
    if statistic.in_year:
609
        start_day = datetime(statistic.in_year, 1, 1)
610
    data_tables = list()
611
    analyses = dict()
612
    if not statistic.in_participants:
613
        run_annual_activity(statistic, start_day, analyses, 'global', str(statistic.in_year) + ' - Tous', data_tables, participant=None)
614
    else:
615
        for participant in statistic.in_participants:
616
            run_annual_activity(statistic, start_day, analyses, participant.id, str(statistic.in_year) + ' - ' + str(participant), data_tables, participant=participant)
617
    return [data_tables]
618

    
619
def patients_per_worker_for_period(statistic):
620
    if not statistic.in_service:
621
        return None
622
    data_tables = []
623
    data = []
624
    data.append(['Intervenants', 'Nombre', 'Patients'])
625
    values = []
626
    if not statistic.in_end_date:
627
        statistic.in_end_date = datetime.today()
628
    if not statistic.in_start_date:
629
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
630
    acts = None
631
    if statistic.in_patients:
632
        acts = Act.objects.filter(date__gte=statistic.in_start_date,
633
            date__lte=statistic.in_end_date,
634
            patient__service=statistic.in_service,
635
            patient__in=statistic.in_patients)
636
    else:
637
        acts = Act.objects.filter(date__gte=statistic.in_start_date,
638
            date__lte=statistic.in_end_date,
639
            patient__service=statistic.in_service)
640
    analyse = dict()
641
    for act in acts:
642
        for intervene in act.doctors.all():
643
            if statistic.in_participants:
644
                if intervene in statistic.in_participants:
645
                    analyse.setdefault(intervene, []).append(str(act.patient))
646
            else:
647
                analyse.setdefault(intervene, []).append(str(act.patient))
648
    o_analyse = OrderedDict(sorted(analyse.items(), key=lambda t: t[0]))
649
    for intervene, patients in o_analyse.iteritems():
650
        lst = list(set(patients))
651
        values.append([str(intervene), len(lst), lst])
652
    data.append(values)
653
    data_tables.append(data)
654
    return [data_tables]
655

    
656
def active_patients_by_state_only(statistic):
657
    if not statistic.in_service:
658
        return None
659
    if not statistic.in_start_date:
660
        statistic.in_start_date = datetime.today()
661
    active_states = None
662
    if statistic.in_service.name == 'CMPP':
663
        active_states = ('TRAITEMENT', 'DIAGNOSTIC')
664
    elif statistic.in_service.name == 'CAMSP':
665
        active_states = ('SUIVI', )
666
    else:
667
        active_states = ('TRAITEMENT', )
668
    patients = [(p.last_name, p.first_name, p.paper_id) \
669
        for p in PatientRecord.objects.filter(service=statistic.in_service) \
670
            if p.get_state_at_day(
671
                statistic.in_start_date).status.type in active_states]
672
    data_tables_set=[[[['En date du :', formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"), len(patients)]]]]
673
    data = []
674
    data.append(['Nom', 'Prénom', 'N° Dossier'])
675
    p_list = []
676
    for ln, fn, pid in patients:
677
        ln = ln or ''
678
        if len(ln) > 1:
679
            ln = ln[0].upper() + ln[1:].lower()
680
        fn = fn or ''
681
        if len(fn) > 1:
682
            fn = fn[0].upper() + fn[1:].lower()
683
        p_list.append((ln, fn, str(pid or '')))
684
    data.append(sorted(p_list,
685
        key=lambda k: k[0]+k[1]))
686
    data_tables_set[0].append(data)
687
    return data_tables_set
688

    
689
def patients_protection(statistic):
690
    if not statistic.in_service:
691
        return None
692
    if not statistic.in_start_date:
693
        statistic.in_start_date = datetime.today()
694
    patients = PatientRecord.objects.filter(protectionstate__isnull=False).distinct()
695
    protection_states = [p.get_protection_state_at_date(
696
            statistic.in_start_date) for p in patients
697
            if p.get_protection_state_at_date(statistic.in_start_date)]
698
    analyse = {}
699
    for state in protection_states:
700
        analyse.setdefault(state.status.name, 0)
701
        analyse[state.status.name] += 1
702
    data_tables_set=[[[['En date du :', formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"), len(protection_states)]]]]
703
    data = []
704
    data.append(['Mesure de protection', 'Nombre de dossiers'])
705
    data.append(analyse.items())
706
    data_tables_set[0].append(data)
707
    return data_tables_set
708

    
709
def active_patients_with_act(statistic):
710
    def process(patients_list, title):
711
        data_tables = []
712
        data = []
713
        data.append([title, len(patients_list), '', ''])
714
        data_tables.append(data)
715
        data = []
716
        data.append(['Nom', 'Prénom', 'N° Dossier'])
717
        patients_values = patients_list.\
718
                values_list('last_name', 'first_name', 'paper_id')
719
        p_list = []
720
        for ln, fn, pid in patients_values:
721
            ln = ln or ''
722
            if len(ln) > 1:
723
                ln = ln[0].upper() + ln[1:].lower()
724
            fn = fn or ''
725
            if len(fn) > 1:
726
                fn = fn[0].upper() + fn[1:].lower()
727
            p_list.append((ln, fn, str(pid or '')))
728
        data.append(sorted(p_list,
729
            key=lambda k: k[0]+k[1]))
730
        data_tables.append(data)
731
        return data_tables
732
    if not statistic.in_service:
733
        return None
734
    if not statistic.in_end_date:
735
        statistic.in_end_date = datetime.today()
736
    if not statistic.in_start_date:
737
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
738
    active_states = None
739
    if statistic.in_service.name == 'CMPP':
740
        active_states = ('TRAITEMENT', 'DIAGNOSTIC')
741
    elif statistic.in_service.name == 'CAMSP':
742
        active_states = ('SUIVI', )
743
    else:
744
        active_states = ('TRAITEMENT', )
745

    
746
    data_tables_set = []
747
    data_tables = []
748
    data = []
749
    data.append(['Période', 'Jours'])
750
    data.append([("%s - %s"
751
        % (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
752
        formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
753
        (statistic.in_end_date-statistic.in_start_date).days+1)])
754
    data_tables.append(data)
755
    data_tables_set.append(data_tables)
756

    
757
    acts_base = Act.objects.filter(
758
        date__gte=statistic.in_start_date,
759
        date__lte=statistic.in_end_date,
760
        patient__service=statistic.in_service)
761
    acts_valide = acts_base.filter(valide=True)
762
    acts_valide_patients_ids = acts_valide.order_by('patient').\
763
        distinct('patient').values_list('patient')
764
    acts_valide_patients = PatientRecord.objects.filter(
765
        id__in=[patient[0] for patient in acts_valide_patients_ids])
766
    all_patients_ids = acts_base.order_by('patient').distinct('patient').\
767
        values_list('patient')
768
    acts_not_valide_patients = PatientRecord.objects.filter(
769
        id__in=[patient[0] for patient in all_patients_ids
770
            if not patient in acts_valide_patients_ids])
771

    
772

    
773
    patients_1 = acts_valide_patients.filter(
774
        last_state__status__type__in=active_states)
775
    patients_2 = acts_valide_patients.exclude(
776
        last_state__status__type__in=active_states)
777
    patients_3 = acts_not_valide_patients.filter(
778
        last_state__status__type__in=active_states)
779
    patients_4 = acts_not_valide_patients.exclude(
780
        last_state__status__type__in=active_states)
781

    
782
    data_tables_set.append(process(patients_1, 'Patients avec un acte validé et dans un état actif'))
783
    data_tables_set.append(process(patients_2, 'Patients avec un acte validé et dans un état non actif'))
784
    data_tables_set.append(process(patients_3, 'Patients sans acte validé et dans un état actif'))
785
    data_tables_set.append(process(patients_4, 'Patients sans acte validé et dans un état non actif'))
786

    
787
    return data_tables_set
788

    
789
def closed_files(statistic):
790
    if not statistic.in_service:
791
        return None
792
    data_tables = []
793
    data1 = []
794
    data1.append(['Période', 'Jours',
795
        'Nombre de dossiers clos durant la période', 'PEC totale', 'PEC moyenne', "Dossiers qui ne sont plus clos"])
796
    data2 = []
797
    data2.append(['Nom', 'Prénom', 'N° Dossier', 'Date de clôture', 'Durée de la PEC', "N'est plus clos"])
798
    if not statistic.in_end_date:
799
        statistic.in_end_date = datetime.today()
800
    if not statistic.in_start_date:
801
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
802
    closed_records = FileState.objects.filter(status__type='CLOS',
803
        date_selected__gte=statistic.in_start_date,
804
        date_selected__lte=statistic.in_end_date). \
805
        order_by('patient').distinct('patient').\
806
        values_list('patient')
807
    closed_records = PatientRecord.objects.filter(service=statistic.in_service, id__in=[patient[0]
808
        for patient in closed_records])
809
    total_pec = 0
810
    p_list = []
811
    not_closed_now = 0
812
    for record in closed_records:
813
        ln = record.last_name or ''
814
        if len(ln) > 1:
815
            ln = ln[0].upper() + ln[1:].lower()
816
        fn = record.first_name or ''
817
        if len(fn) > 1:
818
            fn = fn[0].upper() + fn[1:].lower()
819
        current_state = ''
820
        close_date = record.last_state.date_selected.date()
821
        if record.get_current_state().status.type != 'CLOS':
822
            not_closed_now += 1
823
            current_state = record.get_current_state().status.name + \
824
                ' le ' + formats.date_format(record.get_current_state(). \
825
                date_selected, "SHORT_DATE_FORMAT")
826
            close_date = FileState.objects.filter(status__type='CLOS',
827
                patient=record).order_by('-date_selected')[0].date_selected.date()
828
        p_list.append((ln, fn, str(record.paper_id or ''),
829
            close_date,
830
            record.care_duration_since_last_contact_or_first_act,
831
            current_state))
832
        total_pec += record.care_duration_since_last_contact_or_first_act
833
    data2.append(sorted(p_list,
834
        key=lambda k: k[0]+k[1]))
835
    avg_pec = 0
836
    if closed_records.count() and total_pec:
837
        avg_pec = total_pec/closed_records.count()
838
    data1.append([("%s - %s"
839
        % (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
840
        formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
841
        (statistic.in_end_date-statistic.in_start_date).days+1,
842
        closed_records.count(), total_pec, avg_pec, not_closed_now)])
843
    data_tables.append(data1)
844
    data_tables.append(data2)
845
    return [data_tables]
846

    
847
def patients_details(statistic):
848
    if not statistic.in_service:
849
        return None
850
    data_tables_set = []
851
    if not statistic.in_end_date:
852
        statistic.in_end_date = datetime.today()
853
    if not statistic.in_start_date:
854
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
855
    acts = None
856
    if statistic.in_patients:
857
        acts = Act.objects.filter(date__gte=statistic.in_start_date,
858
            date__lte=statistic.in_end_date,
859
            patient__service=statistic.in_service,
860
            patient__in=statistic.in_patients)
861
    else:
862
        acts = Act.objects.filter(date__gte=statistic.in_start_date,
863
            date__lte=statistic.in_end_date,
864
            patient__service=statistic.in_service)
865
    analyse = dict()
866
    for act in acts:
867
        analyse.setdefault(act.patient, []).append(act)
868
    o_analyse = OrderedDict(sorted(analyse.items(),
869
        key=lambda t: t[0].last_name))
870
    data = []
871
    data.append(['Période', 'Jours',
872
        'Nombre de dossiers'])
873
    data.append([("%s - %s"
874
        % (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
875
        formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
876
        (statistic.in_end_date-statistic.in_start_date).days+1,
877
        len(o_analyse))])
878
    data_tables_set.append([data])
879
    for patient, acts in o_analyse.iteritems():
880
        data_tables = list()
881
        data_tables.append([["%s %s" % (str(patient), str(patient.paper_id))]])
882
        data_tables.append([["Durée de la prise en charge (depuis le premier acte)"], [[patient.care_duration_since_last_contact_or_first_act]]])
883
        data = []
884
        data.append(["Statut de l'acte", 'Nombre'])
885
        values = []
886
        values.append(('Proposés', len(acts)))
887
        np, absent = 0, 0
888
        act_types = dict()
889
        for a in acts:
890
            if a.is_new():
891
                np += 1
892
            elif a.is_absent():
893
                absent += 1
894
            act_types.setdefault(a.act_type, []).append(a)
895
        values.append(('Non pointés', np))
896
        values.append(('Présents', len(acts) - np - absent))
897
        values.append(('Absents', absent))
898
        data.append(values)
899
        data_tables.append(data)
900

    
901
        data = []
902
        data.append(["Types d'acte", "Nombre d'actes proposés", "Nombre d'actes réalisés"])
903
        values = []
904
        for act_type, acts in act_types.iteritems():
905
            values.append((act_type, len(acts), len([a for a in acts if a.is_present()])))
906
        data.append(values)
907
        data_tables.append(data)
908

    
909
        data = []
910
        data.append(["Historique", "Nombre de jours par état"])
911
        values = []
912
        for state, duration in patient.get_states_history_with_duration():
913
            values.append(("%s (%s)" % (state.status.name,
914
                formats.date_format(state.date_selected,
915
                "SHORT_DATE_FORMAT")), duration.days))
916
        data.append(values)
917
        data_tables.append(data)
918

    
919
        contacts = FileState.objects.filter(patient=patient, status__type='ACCUEIL').order_by('date_selected')
920
        recontact = 'Non'
921
        last_contact = None
922
        first_acts_after_contact = None
923
        if len(contacts) == 1:
924
            last_contact = contacts[0]
925
        elif len(contacts) > 1:
926
            recontact = 'Oui'
927
            last_contact = contacts[len(contacts)-1]
928
        if last_contact:
929
            # inscription act
930
            first_acts_after_contact = Act.objects.filter(patient=patient, date__gte=last_contact.date_selected).order_by('date')
931
            if first_acts_after_contact:
932
                first_act_after_contact = first_acts_after_contact[0]
933
                if first_act_after_contact.date <= statistic.in_end_date.date() and first_act_after_contact.date >= statistic.in_start_date.date():
934
                    # inscription during the selected date range.
935
                    waiting_duration = first_act_after_contact.date - last_contact.date_selected.date()
936
                    data = []
937
                    data.append(["Date inscription", "Date accueil", 'Attente', 'Réinscription'])
938
                    values = []
939
                    values.append((first_act_after_contact.date, last_contact.date_selected.date(), waiting_duration.days, recontact))
940
                    data.append(values)
941
                    data_tables.append(data)
942

    
943
        closed_during_range_date = None
944
        try:
945
            closed_during_range_date = FileState.objects.filter(patient=patient, status__type='CLOS',
946
                date_selected__gte=statistic.in_start_date,
947
                date_selected__lte=statistic.in_end_date).latest('date_selected')
948
        except:
949
            pass
950
        care_duration = patient.care_duration_since_last_contact_or_first_act
951
        closure_date = ''
952
        if closed_during_range_date:
953
            closure_date = closed_during_range_date.date_selected.date
954
        reopen = ''
955
        if closed_during_range_date and not patient.exit_date:
956
            reopen = 'Oui'
957
        data = []
958
        data.append(["Durée de la prise en charge", "Clos pendant la période", "Actes suivants la clôture"])
959
        values = []
960
        values.append((patient.care_duration_since_last_contact_or_first_act, closure_date, reopen))
961
        data.append(values)
962
        data_tables.append(data)
963

    
964
        if patient.mdph_requests.exists():
965
            data = []
966
            data.append(["Demande(s) MDPH pendant la période", "Date de la demande", "Demande antérieure à la date de début saisie"])
967
            values = []
968
            for request in patient.mdph_requests.order_by('start_date'):
969
                before = 'Non'
970
                if request.start_date < statistic.in_start_date.date():
971
                    before = 'Oui'
972
                values.append(('MDPH : ' + request.mdph.department, request.start_date, before))
973
            data.append(values)
974
            data_tables.append(data)
975
        if patient.mdph_responses.exists():
976
            data = []
977
            data.append(["Réponse(s) MDPH pendant la période", "Date de début", "Date de fin"])
978
            values = []
979
            for response in patient.mdph_responses.order_by('start_date'):
980
                values.append(('MDPH : ' + response.mdph.department, response.start_date, response.end_date))
981
            data.append(values)
982
            data_tables.append(data)
983
        data_tables_set.append(data_tables)
984

    
985
    return data_tables_set
986

    
987
def patients_synthesis(statistic):
988
    if not statistic.in_service:
989
        return None
990
    data_tables = []
991
    data = []
992
    data.append(['Période', 'Jours',
993
        'Nombre de dossiers avec un acte validé sur la période',
994
        "Nombre d'actes validés sur la période"])
995
    if not statistic.in_end_date:
996
        statistic.in_end_date = datetime.today()
997
    if not statistic.in_start_date:
998
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
999
    acts = Act.objects.filter(valide=True,
1000
        date__gte=statistic.in_start_date,
1001
        date__lte=statistic.in_end_date,
1002
        patient__service=statistic.in_service)
1003
    patients = acts.order_by('patient').distinct('patient').\
1004
        values_list('patient')
1005
    patients = PatientRecord.objects.filter(id__in=[patient[0]
1006
        for patient in patients])
1007

    
1008
    TS = ('TRAITEMENT', 'DIAGNOSTIC', 'SUIVI')
1009
    inscriptions = []
1010
    for patient in patients:
1011
        # Select patient if she has been in treament between the selected dates
1012
        traitement_states_tmp = FileState.objects.filter(patient=patient, status__type__in=TS, date_selected__lte=statistic.in_end_date).order_by('date_selected')
1013
        traitement_states = []
1014
        for ts in traitement_states_tmp:
1015
            if not ts.get_next_state() or ts.get_next_state().date_selected >= statistic.in_start_date:
1016
                traitement_states.append(ts)
1017

    
1018
        # Patient has been in treatment
1019
        # We look for all the treament periods during the selected dates
1020
        # A treament period ends if during the period the file has left treament state
1021
        openings = []
1022
        opening = []
1023
        start = False
1024
        for ts in traitement_states:
1025
            if start:
1026
                openings.append(opening)
1027
                opening = []
1028
                start = False
1029
            if ts.get_next_state() and not ts.get_next_state().status.type in TS and ts.get_next_state().get_next_state() and ts.get_next_state().get_next_state().status.type in TS:
1030
                start = True
1031
            opening.append(ts)
1032
        openings.append(opening)
1033

    
1034
        # The first treatment state is the first one of each period matching the dates selected.
1035
        # But there could be other treatment state before, like diag before treatment.
1036
        # so We have to look for the very first treament state to look at the first act after
1037
        first_tss = []
1038
        for opening in openings:
1039
            if len(opening) >= 1:
1040
                first_ts = opening[0]
1041
                while first_ts.previous_state and first_ts.previous_state.status.type in TS:
1042
                    first_ts = first_ts.previous_state
1043
                contact = None
1044
                if first_ts.previous_state and first_ts.previous_state.status.type=='ACCUEIL':
1045
                    contact = first_ts.previous_state.date_selected.date()
1046
                first_tss.append((contact, first_ts))
1047

    
1048
        # We look to the first act after the datebeginning
1049
        for contact, first_ts in first_tss:
1050
            acts_tmp = Act.objects.filter(valide=True,
1051
                date__gte=first_ts.date_selected,
1052
                patient=patient).order_by('date')
1053
            if acts_tmp and acts_tmp[0].date >= statistic.in_start_date.date() and acts_tmp[0].date <= statistic.in_end_date.date():
1054
                waiting_duration = 0
1055
                if contact:
1056
                    waiting_duration = (acts_tmp[0].date - contact).days
1057
                inscriptions.append((patient, contact, first_ts.date_selected.date(), acts_tmp[0].date, waiting_duration))
1058

    
1059
    if statistic.inscriptions:
1060
        patients = PatientRecord.objects.filter(id__in=[p.id for p, _, _, _, _ in inscriptions])
1061
        acts = acts.filter(patient__in=patients)
1062

    
1063
    nb_patients = patients.count()
1064

    
1065
    data.append([("%s - %s"
1066
        % (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
1067
        formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
1068
        (statistic.in_end_date-statistic.in_start_date).days+1,
1069
        nb_patients, acts.count())])
1070
    data_tables.append(data)
1071
    data = []
1072
    data.append(['Féminin', 'Masculin'])
1073
    data.append([(patients.filter(gender='2').count(),
1074
        patients.filter(gender='1').count())])
1075
    data_tables.append(data)
1076
    data = []
1077
    data.append(['Durée totale de la PEC',
1078
        'Durée moyenne de la PEC par patient'])
1079
    pec_total = sum([p.care_duration_since_last_contact_or_first_act for p in patients])
1080
    data.append([(pec_total, pec_total/nb_patients)])
1081
    data_tables.append(data)
1082

    
1083
    data = []
1084
    data.append(["Etat du dossier à ce jour (%s)" % formats.date_format(datetime.today(), "SHORT_DATE_FORMAT"), 'Nombre de patients'])
1085
    states = dict()
1086
    for patient in patients:
1087
        states.setdefault(patient.get_current_state().status, []).append(patient)
1088
    values = []
1089
    for state, ps in states.iteritems():
1090
        values.append((state.name, len(ps)))
1091
    data.append(values)
1092
    data_tables.append(data)
1093

    
1094
    data = []
1095
    data.append(["Etat du dossier en date de fin (%s)" % formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT"), 'Nombre de patients'])
1096
    states = dict()
1097
    for patient in patients:
1098
        states.setdefault(patient.get_state_at_day(statistic.in_end_date).status, []).append(patient)
1099
    values = []
1100
    for state, ps in states.iteritems():
1101
        values.append((state.name, len(ps)))
1102
    data.append(values)
1103
    data_tables.append(data)
1104

    
1105
    data = []
1106
    data.append(["Inscriptions (premier acte suivant le début d'une phase de traitement dans la période)", "Durée moyenne de l'attente"])
1107
    data.append([(len(inscriptions), sum([wd for _, _, _, _, wd in inscriptions])/len(inscriptions) if len(inscriptions) else 0)])
1108
    data_tables.append(data)
1109

    
1110
    if inscriptions:
1111
        data = []
1112
        data.append(['Nom', 'Prénom', "Numéro papier", "Date premier acte", "Date passage en traitement", "Date de contact", "Attente"])
1113
        values = []
1114
        for patient, contact, first_ts, first_act, waiting_duration in sorted(inscriptions, key=lambda p: (p[0].last_name, p[0].first_name)):
1115
            values.append((patient.last_name, patient.first_name, patient.paper_id, first_act, first_ts, contact, waiting_duration))
1116
        data.append(values)
1117
        data_tables.append(data)
1118

    
1119
    closed_records = FileState.objects.filter(status__type='CLOS',
1120
        date_selected__gte=statistic.in_start_date,
1121
        date_selected__lte=statistic.in_end_date, patient__in=patients). \
1122
        order_by('patient').distinct('patient').\
1123
        values_list('patient')
1124
    closed_records = PatientRecord.objects.filter(service=statistic.in_service, id__in=[patient[0]
1125
        for patient in closed_records])
1126
    total_pec = 0
1127
    not_closed_now = 0
1128
    for record in closed_records:
1129
        if record.get_current_state().status.type != 'CLOS':
1130
            not_closed_now += 1
1131
        total_pec += record.care_duration_since_last_contact_or_first_act
1132
    avg_pec = 0
1133
    if closed_records.count() and total_pec:
1134
        avg_pec = total_pec/closed_records.count()
1135
    if closed_records.count():
1136
        data = []
1137
        data.append(['Clos dans la période', 'Durée totale de la PEC', 'Durée moyenne de la PEC', "Qui ne sont plus clos à ce jour"])
1138
        data.append([(closed_records.count(), total_pec, avg_pec, not_closed_now)])
1139
        data_tables.append(data)
1140

    
1141
    mdph_requests = 0
1142
    mdph_requests_before = 0
1143
    for patient in patients:
1144
        if patient.mdph_requests.exists():
1145
            mdph_requests += 1
1146
            # We only look to the last one
1147
            if patient.mdph_requests.order_by('-start_date')[0].start_date < statistic.in_start_date.date():
1148
                mdph_requests_before +=1
1149
    data = []
1150
    data.append(['Dossier avec une demande MDPH', "Dont la dernière demande a été faite avant la période"])
1151
    data.append([(mdph_requests, mdph_requests_before)])
1152
    data_tables.append(data)
1153

    
1154
    birth_years = dict()
1155
    patients_without_birthyear = []
1156
    for patient in patients:
1157
        try:
1158
            birth_years.setdefault(patient.birthdate.year, []).append(patient)
1159
        except:
1160
            patients_without_birthyear.append(patient)
1161
    data = []
1162
    data.append(['Année de naissance', "Nombre de dossiers", "%"])
1163
    values = []
1164
    for birth_year, pts in birth_years.iteritems():
1165
        values.append((birth_year, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1166
    values.append(('Non renseignée',  len(patients_without_birthyear), "%.2f" % (len(patients_without_birthyear) / float(len(patients)) * 100)))
1167
    data.append(values)
1168
    data_tables.append(data)
1169

    
1170
    if patients_without_birthyear:
1171
        data = []
1172
        data.append(["Patients sans date de naissance"])
1173
        values = [[patients_without_birthyear]]
1174
        data.append(values)
1175
        data_tables.append(data)
1176

    
1177

    
1178
    lower_bounds = [0, 3, 5, 7, 11, 16, 20, 25, 30, 35, 40, 45, 50, 55, 60, 75, 85, 96]
1179
    anap_code = 198
1180
    data = []
1181
    data.append(["Code ANAP", "Tranche d'âge (au %s)" \
1182
        % formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT"),
1183
        "Nombre de dossiers", "%"])
1184
    values = []
1185
    for i in range(len(lower_bounds)):
1186
        lower_bound = lower_bounds[i]
1187
        if i == len(lower_bounds) - 1:
1188
            values.append([anap_code, "De %d ans et plus" % lower_bound, 0, None])
1189
        else:
1190
            values.append([anap_code, "De %d à %d ans" % (lower_bound, lower_bounds[i + 1] - 1), 0, None])
1191
        anap_code += 1
1192
    unknown = 0
1193
    for patient in patients:
1194
        try:
1195
            age = statistic.in_end_date.date() - patient.birthdate
1196
            age = age.days / 365
1197
            i = 0
1198
            while age >= lower_bounds[i+1]:
1199
                i += 1
1200
                if i == len(lower_bounds) - 1:
1201
                    break
1202
            values[i][2] += 1
1203
        except:
1204
            unknown += 1
1205
    for value in values:
1206
        value[3] = "%.2f" % (value[2] / float(len(patients)) * 100)
1207
    values.append(['', "Non renseignée", unknown, "%.2f" % (unknown / float(len(patients)) * 100)])
1208
    data.append(values)
1209
    data_tables.append(data)
1210

    
1211
    jobs = dict()
1212
    no_job = 0
1213
    for patient in patients:
1214
        job = False
1215
        if patient.job_mother:
1216
            jobs.setdefault(patient.job_mother, []).append(patient)
1217
            job = True
1218
        else:
1219
            for contact in patient.contacts.all():
1220
                if contact.parente and contact.parente.name == 'Mère':
1221
                    if contact.job:
1222
                        jobs.setdefault(contact.job, []).append(patient)
1223
                        job = True
1224
                    break
1225
        if not job:
1226
            no_job += 1
1227
    data = []
1228
    data.append(["Profession de la mère", "Nombre de dossiers", "%"])
1229
    values = []
1230
    for job, pts in jobs.iteritems():
1231
        values.append((job, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1232
    values.append(("Non renseignée", no_job, "%.2f" % (no_job / float(len(patients)) * 100)))
1233
    data.append(values)
1234
    data_tables.append(data)
1235

    
1236
    jobs = dict()
1237
    no_job = 0
1238
    for patient in patients:
1239
        job = False
1240
        if patient.job_father:
1241
            jobs.setdefault(patient.job_father, []).append(patient)
1242
            job = True
1243
        else:
1244
            for contact in patient.contacts.all():
1245
                if contact.parente and contact.parente.name == 'Père':
1246
                    if contact.job:
1247
                        jobs.setdefault(contact.job, []).append(patient)
1248
                        job = True
1249
                    break
1250
        if not job:
1251
            no_job += 1
1252
    data = []
1253
    data.append(["Profession du père", "Nombre de dossiers", "%"])
1254
    values = []
1255
    for job, pts in jobs.iteritems():
1256
        values.append((job, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1257
    values.append(("Non renseignée", no_job, "%.2f" % (no_job / float(len(patients)) * 100)))
1258
    data.append(values)
1259
    data_tables.append(data)
1260

    
1261
    provenances = dict()
1262
    unknown = 0
1263
    for patient in patients:
1264
        if patient.provenance:
1265
            provenances.setdefault(patient.provenance, []).append(patient)
1266
        else:
1267
            unknown += 1
1268
    data = []
1269
    data.append(["Provenances", "Nombre de dossiers", "%"])
1270
    values = []
1271
    for provenance, pts in provenances.iteritems():
1272
        values.append((provenance, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1273
    values.append(('Non renseignée', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1274
    data.append(values)
1275
    data_tables.append(data)
1276

    
1277
    outmotives = dict()
1278
    unknown = 0
1279
    for patient in patients:
1280
        if patient.outmotive:
1281
            outmotives.setdefault(patient.outmotive, []).append(patient)
1282
        else:
1283
            unknown += 1
1284
    data = []
1285
    data.append(["Motifs de sortie", "Nombre de dossiers", "%"])
1286
    values = []
1287
    for outmotive, pts in outmotives.iteritems():
1288
        values.append((outmotive, len(pts)))
1289
    values.append(('Non renseigné', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1290
    data.append(values)
1291
    data_tables.append(data)
1292

    
1293
    outtos = dict()
1294
    unknown = 0
1295
    for patient in patients:
1296
        if patient.outto:
1297
            outtos.setdefault(patient.outto, []).append(patient)
1298
        else:
1299
            unknown += 1
1300
    data = []
1301
    data.append(["Orientations", "Nombre de dossiers", "%"])
1302
    values = []
1303
    for outto, pts in outtos.iteritems():
1304
        values.append((outto, len(pts)))
1305
    values.append(('Non renseigné', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1306
    data.append(values)
1307
    data_tables.append(data)
1308

    
1309
    provenance_places = dict()
1310
    unknown = 0
1311
    for patient in patients:
1312
        if patient.provenanceplace:
1313
            provenance_places.setdefault(patient.provenanceplace, []).append(patient)
1314
        else:
1315
            unknown += 1
1316
    data = []
1317
    data.append(["Lieux de provenance", "Nombre de dossiers", "%"])
1318
    values = []
1319
    for provenance_place, pts in provenance_places.iteritems():
1320
        values.append((provenance_place, len(pts)))
1321
    values.append(('Non renseigné', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1322
    data.append(values)
1323
    data_tables.append(data)
1324

    
1325
    return [data_tables]
1326

    
1327
def acts_synthesis(statistic):
1328
    if not statistic.in_service:
1329
        return None
1330
    if not statistic.in_end_date:
1331
        statistic.in_end_date = datetime.today()
1332
    if not statistic.in_start_date:
1333
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1334
    data_tables_set = []
1335
    data_tables = []
1336
    data = []
1337
    data.append(['Période', 'Jours',
1338
        "Nombre d'actes proposés sur la période",
1339
        "Dossiers concernés",
1340
        "Nombre d'actes réalisés sur la période",
1341
        "Dossiers concernés"])
1342
    acts = Act.objects.filter(date__gte=statistic.in_start_date,
1343
        date__lte=statistic.in_end_date,
1344
        patient__service=statistic.in_service)
1345
    len_patients = len(set([a.patient.id for a in acts]))
1346
    acts_present = [a for a in acts if a.is_present()]
1347
    len_patients_present = len(set([a.patient.id for a in acts_present]))
1348
    len_acts_present = len(acts_present)
1349
    data.append([("%s - %s"
1350
        % (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
1351
        formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
1352
        (statistic.in_end_date-statistic.in_start_date).days+1,
1353
        acts.count(), len_patients, len_acts_present, len_patients_present)])
1354
    data_tables.append(data)
1355
    data_tables_set.append(data_tables)
1356

    
1357
    data_tables=[]
1358
    acts_types = dict()
1359
    for act in acts:
1360
        acts_types.setdefault(act.act_type, []).append(act)
1361
    data = []
1362
    data.append(["Types des actes", "Nombre d'actes proposés", "Nombre de dossiers", "Nombre d'actes réalisés", "Nombre de dossiers"])
1363
    values = []
1364
    for act_type, acts in acts_types.iteritems():
1365
        values.append((act_type, len(acts), len(set([a.patient.id for a in acts])), len([a for a in acts if a.is_present()]), len(set([a.patient.id for a in acts if a.is_present()]))))
1366
    data.append(values)
1367
    data_tables.append(data)
1368
    data_tables_set.append(data_tables)
1369

    
1370
    data_tables=[]
1371
    acts_count_participants = dict()
1372
    for act in acts_present:
1373
        acts_count_participants.setdefault(act.doctors.count(), []).append(act)
1374
    data = []
1375
    data.append(["Nombre d'intervenants des actes réalisés", "Nombre d'actes", "Nombre de dossiers concernés"])
1376
    values = []
1377
    for number, acts_counted in acts_count_participants.iteritems():
1378
        values.append((number, len(acts_counted), len(set([a.patient.id for a in acts_counted]))))
1379
    data.append(values)
1380
    data_tables.append(data)
1381
    data_tables_set.append(data_tables)
1382

    
1383
    for act_type, acts in acts_types.iteritems():
1384
        data_tables=[]
1385
        analysis = {'Non pointés': 0,
1386
            'Reportés': 0, 'Absents': 0, 'Présents': 0}
1387
        for a in acts:
1388
            if a.is_new():
1389
                analysis['Non pointés'] += 1
1390
            elif a.is_absent():
1391
                state = a.get_state()
1392
                if state.state_name == 'REPORTE':
1393
                    analysis['Reportés'] += 1
1394
                else:
1395
                    analysis['Absents'] += 1
1396
            else:
1397
                analysis['Présents'] += 1
1398
        data = []
1399
        data.append(["Type d'acte", act_type])
1400
        values = []
1401
        for status, number in analysis.iteritems():
1402
            values.append((status, number))
1403
        data.append(values)
1404
        data_tables.append(data)
1405
        acts_type_patients = {}
1406
        for act in acts:
1407
            acts_type_patients.setdefault(act.patient, []).append(act)
1408
        data = []
1409
        data.append(["Patient", "Actes proposés", "Actes réalisés"])
1410
        values = []
1411
        for patient, acts_type in acts_type_patients.iteritems():
1412
            values.append((patient, len(acts_type), len([a for a in acts_type if a.is_present()])))
1413
        data.append(values)
1414
        data_tables.append(data)
1415
        data_tables_set.append(data_tables)
1416

    
1417
    return data_tables_set
1418

    
1419
def acts_synthesis_cmpp(statistic):
1420
    data_tables_set = []
1421
    if not statistic.in_service:
1422
        return None
1423
    if not statistic.in_end_date:
1424
        statistic.in_end_date = datetime.today()
1425
    if not statistic.in_start_date:
1426
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1427
    acts = Act.objects.filter(date__gte=statistic.in_start_date,
1428
        date__lte=statistic.in_end_date,
1429
        patient__service=statistic.in_service)
1430
    acts_billed = acts.filter(is_billed=True)
1431
    patients_billed = dict()
1432
    for act in acts_billed:
1433
        patients_billed.setdefault(act.patient, [False, False])
1434
        if act.get_hc_tag() and act.get_hc_tag()[0] == 'D':
1435
            patients_billed[act.patient][0] = True
1436
        elif act.get_hc_tag() and act.get_hc_tag()[0] == 'T':
1437
            patients_billed[act.patient][1] = True
1438
    values1, values2, values3 = [], [], []
1439
    for patient, vals in patients_billed.iteritems():
1440
        pfields = [patient.last_name, patient.first_name, patient.paper_id]
1441
        if vals == [True, False]:
1442
            values1.append(pfields)
1443
        elif vals == [False, True]:
1444
            values2.append(pfields)
1445
        elif vals == [True, True]:
1446
            values3.append(pfields)
1447
    cols = ['Nom', 'Prénom', 'Numéro de dossier']
1448
    data_tables_set.append([[['Seulement facturé en diagnostic'], [[len(values1)]]], [cols, sorted(values1, key=lambda t: t[0])]])
1449
    data_tables_set.append([[['Seulement facturé en traitement'], [[len(values2)]]], [cols, sorted(values2, key=lambda t: t[0])]])
1450
    data_tables_set.append([[['Facturé en diagnostic et en traitement'], [[len(values3)]]], [cols, sorted(values3, key=lambda t: t[0])]])
1451
    return data_tables_set
1452

    
1453
def mises(statistic):
1454
    if not statistic.in_service:
1455
        return None
1456
    if not statistic.in_end_date:
1457
        statistic.in_end_date = datetime.today()
1458
    if not statistic.in_start_date:
1459
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1460
    acts = Act.objects.filter(valide='True',
1461
        date__gte=statistic.in_start_date,
1462
        date__lte=statistic.in_end_date,
1463
        patient__service=statistic.in_service)
1464
    patients = acts.order_by('patient').distinct('patient').\
1465
        values_list('patient')
1466
    patients = PatientRecord.objects.filter(id__in=[patient[0]
1467
        for patient in patients])
1468
    pathologies = dict()
1469
    for patient in patients:
1470
        for pathology in patient.mises_1.all():
1471
            pathologies.setdefault(pathology, 0)
1472
            pathologies[pathology] += 1
1473
        for pathology in patient.mises_2.all():
1474
            pathologies.setdefault(pathology, 0)
1475
            pathologies[pathology] += 1
1476
        for pathology in patient.mises_3.all():
1477
            pathologies.setdefault(pathology, 0)
1478
            pathologies[pathology] += 1
1479
    data = [['Pathologies MISES', 'Nombre de patients concernés']]
1480
    data.append(OrderedDict(sorted(pathologies.items(), key=lambda t: t[0].ordering_code)).items())
1481
    return [[data]]
1482

    
1483
def deficiencies(statistic):
1484
    if not statistic.in_service:
1485
        return None
1486
    if not statistic.in_end_date:
1487
        statistic.in_end_date = datetime.today()
1488
    if not statistic.in_start_date:
1489
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1490
    acts = Act.objects.filter(valide='True',
1491
        date__gte=statistic.in_start_date,
1492
        date__lte=statistic.in_end_date,
1493
        patient__service=statistic.in_service)
1494
    patients = acts.order_by('patient').distinct('patient').\
1495
        values_list('patient')
1496
    patients = PatientRecord.objects.filter(id__in=[patient[0]
1497
        for patient in patients])
1498
    deficiencies_three = ('deficiency_intellectual',
1499
            'deficiency_autism_and_other_ted',
1500
            'deficiency_mental_disorder', 'deficiency_learning_disorder',
1501
            'deficiency_auditory', 'deficiency_visual', 'deficiency_motor',
1502
            'deficiency_metabolic_disorder', 'deficiency_brain_damage',
1503
            'deficiency_behavioral_disorder', 'deficiency_other_disorder')
1504
    data = [['Déficiences', 'Nombre de patients concernés'], []]
1505
    for deficiency in deficiencies_three:
1506
        name = PatientRecord._meta.get_field_by_name(deficiency)[0].verbose_name
1507
        filter_dict = {deficiency: 1}
1508
        data[1].append((name + ' à titre principal', patients.filter(**filter_dict).count()))
1509
        filter_dict = {deficiency: 2}
1510
        data[1].append((name + ' à titre associé', patients.filter(**filter_dict).count()))
1511
    name = PatientRecord._meta.get_field_by_name('deficiency_polyhandicap')[0].verbose_name
1512
    data[1].append((name, patients.filter(deficiency_polyhandicap=True).count()))
1513
    name = PatientRecord._meta.get_field_by_name('deficiency_in_diagnostic')[0].verbose_name
1514
    data[1].append((name, patients.filter(deficiency_in_diagnostic=True).count()))
1515
    return [[data]]
1516

    
1517
class Statistic(models.Model):
1518
    patients = models.ManyToManyField('dossiers.PatientRecord',
1519
            null=True, blank=True, default=None)
1520
    participants = models.ManyToManyField('personnes.People',
1521
            null=True, blank=True, default=None)
1522
    in_start_date = None
1523
    in_end_date = None
1524
    in_service = None
1525
    in_participants = None
1526
    in_patients = None
1527
    in_year = None
1528
    inscriptions = False
1529

    
1530
    def __init__(self, name=None, inputs=dict()):
1531
        self.name = name
1532
        params = STATISTICS.get(name, {})
1533
        self.display_name = params['display_name']
1534
        self.category = params['category']
1535
        self.inputs = inputs
1536
        self.in_participants = list()
1537
        participants = inputs.get('participants')
1538
        if participants:
1539
            p_str_ids = [p for p in participants.split('|') if p]
1540
            for str_id in p_str_ids:
1541
                try:
1542
                    self.in_participants.append(Worker.objects.get(pk=int(str_id)))
1543
                except:
1544
                    pass
1545
        self.in_patients = list()
1546
        patients = inputs.get('patients')
1547
        if patients:
1548
            p_str_ids = [p for p in patients.split('|') if p]
1549
            for str_id in p_str_ids:
1550
                try:
1551
                    self.in_patients.append(PatientRecord.objects.get(pk=int(str_id)))
1552
                except:
1553
                    pass
1554
        self.in_service = inputs.get('service')
1555
        self.in_start_date = None
1556
        try:
1557
            self.in_start_date = datetime.strptime(inputs.get('start_date'),
1558
                "%d/%m/%Y")
1559
            self.in_year = self.in_start_date.year
1560
        except:
1561
            pass
1562
        self.in_end_date = None
1563
        try:
1564
            self.in_end_date = datetime.strptime(inputs.get('end_date'),
1565
                "%d/%m/%Y")
1566
        except:
1567
            pass
1568
        self.inscriptions = inputs.get('inscriptions')
1569

    
1570
    def get_data(self):
1571
        func = globals()[self.name]
1572
        data = func(self)
1573
        self.data = [[[["Date du jour", "Service", "Nom statistique"],
1574
            [[formats.date_format(datetime.today(), "SHORT_DATE_FORMAT"),
1575
            self.in_service, STATISTICS[self.name]['display_name']]]]]] + data
1576
        return self.data
1577

    
1578
    def render_to_csv(self):
1579
        _delimiter = ';'
1580
        _quotechar = '|'
1581
        _doublequote = True
1582
        _skipinitialspace = False
1583
        _lineterminator = '\r\n'
1584
        _quoting = csv.QUOTE_MINIMAL
1585
        if getattr(settings, 'CSVPROFILE', None):
1586
            csv_profile = settings.CSVPROFILE
1587
            _delimiter = csv_profile.get('delimiter', ';')
1588
            _quotechar = csv_profile.get('quotechar', '|')
1589
            _doublequote = csv_profile.get('doublequote', True)
1590
            _skipinitialspace = csv_profile.get('skipinitialspace', False)
1591
            _lineterminator = csv_profile.get('lineterminator', '\r\n')
1592
            _quoting = csv_profile.get('quoting', csv.QUOTE_MINIMAL)
1593
        class CSVProfile(csv.Dialect):
1594
            delimiter = _delimiter
1595
            quotechar = _quotechar
1596
            doublequote = _doublequote
1597
            skipinitialspace = _skipinitialspace
1598
            lineterminator = _lineterminator
1599
            quoting = _quoting
1600
        csv.register_dialect('csv_profile', CSVProfile())
1601
        encoding = getattr(settings, 'CSV_ENCODING', 'utf-8')
1602
#        Python 3: , encoding=encoding
1603
#        with tempfile.NamedTemporaryFile(delete=False) as temp_out_csv:
1604
#            try:
1605
#                writer = csv.writer(temp_out_csv, dialect='csv_profile')
1606
#                for data_set in self.data:
1607
#                    for data in data_set:
1608
#                        writer.writerow(data[0])
1609
#                        if len(data) > 1:
1610
#                            for d in data[1]:
1611
#                                writer.writerow(d)
1612
#                        writer.writerow([])
1613
#                    writer.writerow([])
1614
#                return temp_out_csv.name
1615
#            except Exception, e:
1616
#                print e
1617
#                try:
1618
#                    os.unlink(temp_out_pdf.name)
1619
#                except:
1620
#                    pass
1621

    
1622
        import codecs
1623
        filename = None
1624
        with tempfile.NamedTemporaryFile(delete=False) as temp_out_csv:
1625
            filename = temp_out_csv.name
1626
            temp_out_csv.close()
1627
        with codecs.open(filename, 'w+b', encoding=encoding) as encoded_f:
1628
            try:
1629
                writer = csv.writer(encoded_f, dialect='csv_profile')
1630
                for data_set in self.data:
1631
                    for data in data_set:
1632
                        writer.writerow(data[0])
1633
                        if len(data) > 1:
1634
                            for d in data[1]:
1635
                                writer.writerow(d)
1636
                        writer.writerow([])
1637
                    writer.writerow([])
1638
                return filename
1639
            except:
1640
                try:
1641
                    os.unlink(temp_out_pdf.name)
1642
                except:
1643
                    pass
1644

    
1645
    def get_file(self):
1646
        self.get_data()
1647
        return self.render_to_csv()
(5-5/8)