Project

General

Profile

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

calebasse / calebasse / statistics / statistics.py @ 80bdfd4a

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

    
846
    days_states = {}
847
    for record in closed_records:
848
        for state, duration in record.get_states_history_with_duration():
849
            days_states.setdefault(state.status, 0)
850
            days_states[state.status] += duration.days
851
    data = []
852
    data.append(["Etat des dossiers", "Nombre de jours total", "Nombre de jours moyen par dossier"])
853
    values = []
854
    for status, duration in days_states.iteritems():
855
        values.append((status.name, duration, duration/closed_records.count()))
856
    data.append(values)
857
    data_tables.append(data)
858
    return [data_tables]
859

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

    
914
        data = []
915
        data.append(["Types d'acte", "Nombre d'actes proposés", "Nombre d'actes réalisés"])
916
        values = []
917
        for act_type, acts in act_types.iteritems():
918
            values.append((act_type, len(acts), len([a for a in acts if a.is_present()])))
919
        data.append(values)
920
        data_tables.append(data)
921

    
922
        data = []
923
        data.append(["Historique", "Nombre de jours par état"])
924
        values = []
925
        for state, duration in patient.get_states_history_with_duration():
926
            values.append(("%s (%s)" % (state.status.name,
927
                formats.date_format(state.date_selected,
928
                "SHORT_DATE_FORMAT")), duration.days))
929
        data.append(values)
930
        data_tables.append(data)
931

    
932
        contacts = FileState.objects.filter(patient=patient, status__type='ACCUEIL').order_by('date_selected')
933
        recontact = 'Non'
934
        last_contact = None
935
        first_acts_after_contact = None
936
        if len(contacts) == 1:
937
            last_contact = contacts[0]
938
        elif len(contacts) > 1:
939
            recontact = 'Oui'
940
            last_contact = contacts[len(contacts)-1]
941
        if last_contact:
942
            # inscription act
943
            first_acts_after_contact = Act.objects.filter(patient=patient, date__gte=last_contact.date_selected).order_by('date')
944
            if first_acts_after_contact:
945
                first_act_after_contact = first_acts_after_contact[0]
946
                if first_act_after_contact.date <= statistic.in_end_date.date() and first_act_after_contact.date >= statistic.in_start_date.date():
947
                    # inscription during the selected date range.
948
                    waiting_duration = first_act_after_contact.date - last_contact.date_selected.date()
949
                    data = []
950
                    data.append(["Date inscription", "Date accueil", 'Attente', 'Réinscription'])
951
                    values = []
952
                    values.append((first_act_after_contact.date, last_contact.date_selected.date(), waiting_duration.days, recontact))
953
                    data.append(values)
954
                    data_tables.append(data)
955

    
956
        closed_during_range_date = None
957
        try:
958
            closed_during_range_date = FileState.objects.filter(patient=patient, status__type='CLOS',
959
                date_selected__gte=statistic.in_start_date,
960
                date_selected__lte=statistic.in_end_date).latest('date_selected')
961
        except:
962
            pass
963
        care_duration = patient.care_duration_since_last_contact_or_first_act
964
        closure_date = ''
965
        if closed_during_range_date:
966
            closure_date = closed_during_range_date.date_selected.date
967
        reopen = ''
968
        if closed_during_range_date and not patient.exit_date:
969
            reopen = 'Oui'
970
        data = []
971
        data.append(["Durée de la prise en charge", "Clos pendant la période", "Actes suivants la clôture"])
972
        values = []
973
        values.append((patient.care_duration_since_last_contact_or_first_act, closure_date, reopen))
974
        data.append(values)
975
        data_tables.append(data)
976

    
977
        if patient.mdph_requests.exists():
978
            data = []
979
            data.append(["Demande(s) MDPH pendant la période", "Date de la demande", "Demande antérieure à la date de début saisie"])
980
            values = []
981
            for request in patient.mdph_requests.order_by('start_date'):
982
                before = 'Non'
983
                if request.start_date < statistic.in_start_date.date():
984
                    before = 'Oui'
985
                values.append(('MDPH : ' + request.mdph.department, request.start_date, before))
986
            data.append(values)
987
            data_tables.append(data)
988
        if patient.mdph_responses.exists():
989
            data = []
990
            data.append(["Réponse(s) MDPH pendant la période", "Date de début", "Date de fin"])
991
            values = []
992
            for response in patient.mdph_responses.order_by('start_date'):
993
                values.append(('MDPH : ' + response.mdph.department, response.start_date, response.end_date))
994
            data.append(values)
995
            data_tables.append(data)
996
        data_tables_set.append(data_tables)
997

    
998
    return data_tables_set
999

    
1000
def patients_synthesis(statistic):
1001
    if not statistic.in_service:
1002
        return None
1003
    data_tables = []
1004
    data = []
1005
    data.append(['Période', 'Jours',
1006
        'Nombre de dossiers avec un acte validé sur la période',
1007
        "Nombre d'actes validés sur la période"])
1008
    if not statistic.in_end_date:
1009
        statistic.in_end_date = datetime.today()
1010
    if not statistic.in_start_date:
1011
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1012
    acts = Act.objects.filter(valide=True,
1013
        date__gte=statistic.in_start_date,
1014
        date__lte=statistic.in_end_date,
1015
        patient__service=statistic.in_service)
1016
    patients = acts.order_by('patient').distinct('patient').\
1017
        values_list('patient')
1018
    patients = PatientRecord.objects.filter(id__in=[patient[0]
1019
        for patient in patients])
1020

    
1021
    TS = ('TRAITEMENT', 'DIAGNOSTIC', 'SUIVI')
1022
    inscriptions = []
1023
    for patient in patients:
1024
        # Select patient if she has been in treament between the selected dates
1025
        traitement_states_tmp = FileState.objects.filter(patient=patient, status__type__in=TS, date_selected__lte=statistic.in_end_date).order_by('date_selected')
1026
        traitement_states = []
1027
        for ts in traitement_states_tmp:
1028
            if not ts.get_next_state() or ts.get_next_state().date_selected >= statistic.in_start_date:
1029
                traitement_states.append(ts)
1030

    
1031
        # Patient has been in treatment
1032
        # We look for all the treament periods during the selected dates
1033
        # A treament period ends if during the period the file has left treament state
1034
        openings = []
1035
        opening = []
1036
        start = False
1037
        for ts in traitement_states:
1038
            if start:
1039
                openings.append(opening)
1040
                opening = []
1041
                start = False
1042
            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:
1043
                start = True
1044
            opening.append(ts)
1045
        openings.append(opening)
1046

    
1047
        # The first treatment state is the first one of each period matching the dates selected.
1048
        # But there could be other treatment state before, like diag before treatment.
1049
        # so We have to look for the very first treament state to look at the first act after
1050
        first_tss = []
1051
        for opening in openings:
1052
            if len(opening) >= 1:
1053
                first_ts = opening[0]
1054
                while first_ts.previous_state and first_ts.previous_state.status.type in TS:
1055
                    first_ts = first_ts.previous_state
1056
                contact = None
1057
                if first_ts.previous_state and first_ts.previous_state.status.type=='ACCUEIL':
1058
                    contact = first_ts.previous_state.date_selected.date()
1059
                first_tss.append((contact, first_ts))
1060

    
1061
        # We look to the first act after the datebeginning
1062
        for contact, first_ts in first_tss:
1063
            acts_tmp = Act.objects.filter(valide=True,
1064
                date__gte=first_ts.date_selected,
1065
                patient=patient).order_by('date')
1066
            if acts_tmp and acts_tmp[0].date >= statistic.in_start_date.date() and acts_tmp[0].date <= statistic.in_end_date.date():
1067
                waiting_duration = 0
1068
                if contact:
1069
                    waiting_duration = (acts_tmp[0].date - contact).days
1070
                inscriptions.append((patient, contact, first_ts.date_selected.date(), acts_tmp[0].date, waiting_duration))
1071

    
1072
    if statistic.inscriptions:
1073
        patients = PatientRecord.objects.filter(id__in=[p.id for p, _, _, _, _ in inscriptions])
1074
        acts = acts.filter(patient__in=patients)
1075

    
1076
    nb_patients = patients.count()
1077

    
1078
    data.append([("%s - %s"
1079
        % (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
1080
        formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
1081
        (statistic.in_end_date-statistic.in_start_date).days+1,
1082
        nb_patients, acts.count())])
1083
    data_tables.append(data)
1084
    data = []
1085
    data.append(['Féminin', 'Masculin'])
1086
    data.append([(patients.filter(gender='2').count(),
1087
        patients.filter(gender='1').count())])
1088
    data_tables.append(data)
1089
    data = []
1090
    data.append(['Durée totale de la PEC',
1091
        'Durée moyenne de la PEC par patient'])
1092
    pec_total = sum([p.care_duration_since_last_contact_or_first_act for p in patients])
1093
    data.append([(pec_total, pec_total/nb_patients)])
1094
    data_tables.append(data)
1095

    
1096
    data = []
1097
    data.append(["Etat du dossier à ce jour (%s)" % formats.date_format(datetime.today(), "SHORT_DATE_FORMAT"), 'Nombre de patients'])
1098
    states = dict()
1099
    for patient in patients:
1100
        states.setdefault(patient.get_current_state().status, []).append(patient)
1101
    values = []
1102
    for state, ps in states.iteritems():
1103
        values.append((state.name, len(ps)))
1104
    data.append(values)
1105
    data_tables.append(data)
1106

    
1107
    data = []
1108
    data.append(["Etat du dossier en date de fin (%s)" % formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT"), 'Nombre de patients'])
1109
    states = dict()
1110
    for patient in patients:
1111
        states.setdefault(patient.get_state_at_day(statistic.in_end_date).status, []).append(patient)
1112
    values = []
1113
    for state, ps in states.iteritems():
1114
        values.append((state.name, len(ps)))
1115
    data.append(values)
1116
    data_tables.append(data)
1117

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

    
1123
    if inscriptions:
1124
        data = []
1125
        data.append(['Nom', 'Prénom', "Numéro papier", "Date premier acte", "Date passage en traitement", "Date de contact", "Attente"])
1126
        values = []
1127
        for patient, contact, first_ts, first_act, waiting_duration in sorted(inscriptions, key=lambda p: (p[0].last_name, p[0].first_name)):
1128
            values.append((patient.last_name, patient.first_name, patient.paper_id, first_act, first_ts, contact, waiting_duration))
1129
        data.append(values)
1130
        data_tables.append(data)
1131

    
1132
    closed_records = FileState.objects.filter(status__type='CLOS',
1133
        date_selected__gte=statistic.in_start_date,
1134
        date_selected__lte=statistic.in_end_date, patient__in=patients). \
1135
        order_by('patient').distinct('patient').\
1136
        values_list('patient')
1137
    closed_records = PatientRecord.objects.filter(service=statistic.in_service, id__in=[patient[0]
1138
        for patient in closed_records])
1139
    total_pec = 0
1140
    not_closed_now = 0
1141
    for record in closed_records:
1142
        if record.get_current_state().status.type != 'CLOS':
1143
            not_closed_now += 1
1144
        total_pec += record.care_duration_since_last_contact_or_first_act
1145
    avg_pec = 0
1146
    if closed_records.count() and total_pec:
1147
        avg_pec = total_pec/closed_records.count()
1148
    if closed_records.count():
1149
        data = []
1150
        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"])
1151
        data.append([(closed_records.count(), total_pec, avg_pec, not_closed_now)])
1152
        data_tables.append(data)
1153

    
1154
    mdph_requests = 0
1155
    mdph_requests_before = 0
1156
    for patient in patients:
1157
        if patient.mdph_requests.exists():
1158
            mdph_requests += 1
1159
            # We only look to the last one
1160
            if patient.mdph_requests.order_by('-start_date')[0].start_date < statistic.in_start_date.date():
1161
                mdph_requests_before +=1
1162
    data = []
1163
    data.append(['Dossier avec une demande MDPH', "Dont la dernière demande a été faite avant la période"])
1164
    data.append([(mdph_requests, mdph_requests_before)])
1165
    data_tables.append(data)
1166

    
1167
    birth_years = dict()
1168
    patients_without_birthyear = []
1169
    for patient in patients:
1170
        try:
1171
            birth_years.setdefault(patient.birthdate.year, []).append(patient)
1172
        except:
1173
            patients_without_birthyear.append(patient)
1174
    data = []
1175
    data.append(['Année de naissance', "Nombre de dossiers", "%"])
1176
    values = []
1177
    for birth_year, pts in birth_years.iteritems():
1178
        values.append((birth_year, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1179
    values.append(('Non renseignée',  len(patients_without_birthyear), "%.2f" % (len(patients_without_birthyear) / float(len(patients)) * 100)))
1180
    data.append(values)
1181
    data_tables.append(data)
1182

    
1183
    if patients_without_birthyear:
1184
        data = []
1185
        data.append(["Patients sans date de naissance"])
1186
        values = [[patients_without_birthyear]]
1187
        data.append(values)
1188
        data_tables.append(data)
1189

    
1190

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

    
1224
    jobs = dict()
1225
    no_job = 0
1226
    for patient in patients:
1227
        job = False
1228
        if patient.job_mother:
1229
            jobs.setdefault(patient.job_mother, []).append(patient)
1230
            job = True
1231
        else:
1232
            for contact in patient.contacts.all():
1233
                if contact.parente and contact.parente.name == 'Mère':
1234
                    if contact.job:
1235
                        jobs.setdefault(contact.job, []).append(patient)
1236
                        job = True
1237
                    break
1238
        if not job:
1239
            no_job += 1
1240
    data = []
1241
    data.append(["Profession de la mère", "Nombre de dossiers", "%"])
1242
    values = []
1243
    for job, pts in jobs.iteritems():
1244
        values.append((job, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1245
    values.append(("Non renseignée", no_job, "%.2f" % (no_job / float(len(patients)) * 100)))
1246
    data.append(values)
1247
    data_tables.append(data)
1248

    
1249
    jobs = dict()
1250
    no_job = 0
1251
    for patient in patients:
1252
        job = False
1253
        if patient.job_father:
1254
            jobs.setdefault(patient.job_father, []).append(patient)
1255
            job = True
1256
        else:
1257
            for contact in patient.contacts.all():
1258
                if contact.parente and contact.parente.name == 'Père':
1259
                    if contact.job:
1260
                        jobs.setdefault(contact.job, []).append(patient)
1261
                        job = True
1262
                    break
1263
        if not job:
1264
            no_job += 1
1265
    data = []
1266
    data.append(["Profession du père", "Nombre de dossiers", "%"])
1267
    values = []
1268
    for job, pts in jobs.iteritems():
1269
        values.append((job, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1270
    values.append(("Non renseignée", no_job, "%.2f" % (no_job / float(len(patients)) * 100)))
1271
    data.append(values)
1272
    data_tables.append(data)
1273

    
1274
    provenances = dict()
1275
    unknown = 0
1276
    for patient in patients:
1277
        if patient.provenance:
1278
            provenances.setdefault(patient.provenance, []).append(patient)
1279
        else:
1280
            unknown += 1
1281
    data = []
1282
    data.append(["Provenances", "Nombre de dossiers", "%"])
1283
    values = []
1284
    for provenance, pts in provenances.iteritems():
1285
        values.append((provenance, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1286
    values.append(('Non renseignée', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1287
    data.append(values)
1288
    data_tables.append(data)
1289

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

    
1306
    outtos = dict()
1307
    unknown = 0
1308
    for patient in patients:
1309
        if patient.outto:
1310
            outtos.setdefault(patient.outto, []).append(patient)
1311
        else:
1312
            unknown += 1
1313
    data = []
1314
    data.append(["Orientations", "Nombre de dossiers", "%"])
1315
    values = []
1316
    for outto, pts in outtos.iteritems():
1317
        values.append((outto, len(pts)))
1318
    values.append(('Non renseigné', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1319
    data.append(values)
1320
    data_tables.append(data)
1321

    
1322
    provenance_places = dict()
1323
    unknown = 0
1324
    for patient in patients:
1325
        if patient.provenanceplace:
1326
            provenance_places.setdefault(patient.provenanceplace, []).append(patient)
1327
        else:
1328
            unknown += 1
1329
    data = []
1330
    data.append(["Lieux de provenance", "Nombre de dossiers", "%"])
1331
    values = []
1332
    for provenance_place, pts in provenance_places.iteritems():
1333
        values.append((provenance_place, len(pts)))
1334
    values.append(('Non renseigné', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1335
    data.append(values)
1336
    data_tables.append(data)
1337

    
1338
    return [data_tables]
1339

    
1340
def acts_synthesis(statistic):
1341
    if not statistic.in_service:
1342
        return None
1343
    if not statistic.in_end_date:
1344
        statistic.in_end_date = datetime.today()
1345
    if not statistic.in_start_date:
1346
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1347
    data_tables_set = []
1348
    data_tables = []
1349
    data = []
1350
    data.append(['Période', 'Jours',
1351
        "Nombre d'actes proposés sur la période",
1352
        "Dossiers concernés",
1353
        "Nombre d'actes réalisés sur la période",
1354
        "Dossiers concernés"])
1355
    acts = Act.objects.filter(date__gte=statistic.in_start_date,
1356
        date__lte=statistic.in_end_date,
1357
        patient__service=statistic.in_service)
1358
    len_patients = len(set([a.patient.id for a in acts]))
1359
    acts_present = [a for a in acts if a.is_present()]
1360
    len_patients_present = len(set([a.patient.id for a in acts_present]))
1361
    len_acts_present = len(acts_present)
1362
    data.append([("%s - %s"
1363
        % (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
1364
        formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
1365
        (statistic.in_end_date-statistic.in_start_date).days+1,
1366
        acts.count(), len_patients, len_acts_present, len_patients_present)])
1367
    data_tables.append(data)
1368
    data_tables_set.append(data_tables)
1369

    
1370
    data_tables=[]
1371
    acts_types = dict()
1372
    for act in acts:
1373
        acts_types.setdefault(act.act_type, []).append(act)
1374
    data = []
1375
    data.append(["Types des actes", "Nombre d'actes proposés", "Nombre de dossiers", "Nombre d'actes réalisés", "Nombre de dossiers"])
1376
    values = []
1377
    for act_type, acts in sorted(acts_types.items(), key=lambda t: t[0].name):
1378
        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()]))))
1379
    data.append(values)
1380
    data_tables.append(data)
1381
    data_tables_set.append(data_tables)
1382

    
1383
    data_tables=[]
1384
    acts_count_participants = dict()
1385
    for act in acts_present:
1386
        acts_count_participants.setdefault(act.doctors.count(), []).append(act)
1387
    data = []
1388
    data.append(["Nombre d'intervenants des actes réalisés", "Nombre d'actes", "Nombre de dossiers concernés"])
1389
    values = []
1390
    for number, acts_counted in acts_count_participants.iteritems():
1391
        values.append((number, len(acts_counted), len(set([a.patient.id for a in acts_counted]))))
1392
    data.append(values)
1393
    data_tables.append(data)
1394
    data_tables_set.append(data_tables)
1395

    
1396
    for act_type, acts in acts_types.iteritems():
1397
        data_tables=[]
1398
        analysis = {'Non pointés': 0,
1399
            'Reportés': 0, 'Absents': 0, 'Présents': 0}
1400
        for a in acts:
1401
            if a.is_new():
1402
                analysis['Non pointés'] += 1
1403
            elif a.is_absent():
1404
                state = a.get_state()
1405
                if state.state_name == 'REPORTE':
1406
                    analysis['Reportés'] += 1
1407
                else:
1408
                    analysis['Absents'] += 1
1409
            else:
1410
                analysis['Présents'] += 1
1411
        data = []
1412
        data.append(["Type d'acte", act_type])
1413
        values = []
1414
        for status, number in analysis.iteritems():
1415
            values.append((status, number))
1416
        data.append(values)
1417
        data_tables.append(data)
1418
        acts_type_patients = {}
1419
        for act in acts:
1420
            acts_type_patients.setdefault(act.patient, []).append(act)
1421
        data = []
1422
        data.append(["Patient", "Actes proposés", "Actes réalisés"])
1423
        values = []
1424
        for patient, acts_type in acts_type_patients.iteritems():
1425
            values.append((patient, len(acts_type), len([a for a in acts_type if a.is_present()])))
1426
        data.append(values)
1427
        data_tables.append(data)
1428
        data_tables_set.append(data_tables)
1429

    
1430
    return data_tables_set
1431

    
1432
def acts_synthesis_cmpp(statistic):
1433
    data_tables_set = []
1434
    if not statistic.in_service:
1435
        return None
1436
    if not statistic.in_end_date:
1437
        statistic.in_end_date = datetime.today()
1438
    if not statistic.in_start_date:
1439
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1440
    acts = Act.objects.filter(date__gte=statistic.in_start_date,
1441
        date__lte=statistic.in_end_date,
1442
        patient__service=statistic.in_service)
1443
    acts_billed = acts.filter(is_billed=True)
1444
    patients_billed = dict()
1445
    for act in acts_billed:
1446
        patients_billed.setdefault(act.patient, [False, False])
1447
        if act.get_hc_tag() and act.get_hc_tag()[0] == 'D':
1448
            patients_billed[act.patient][0] = True
1449
        elif act.get_hc_tag() and act.get_hc_tag()[0] == 'T':
1450
            patients_billed[act.patient][1] = True
1451
    values1, values2, values3 = [], [], []
1452
    for patient, vals in patients_billed.iteritems():
1453
        pfields = [patient.last_name, patient.first_name, patient.paper_id]
1454
        if vals == [True, False]:
1455
            values1.append(pfields)
1456
        elif vals == [False, True]:
1457
            values2.append(pfields)
1458
        elif vals == [True, True]:
1459
            values3.append(pfields)
1460
    cols = ['Nom', 'Prénom', 'Numéro de dossier']
1461
    data_tables_set.append([[['Seulement facturé en diagnostic'], [[len(values1)]]], [cols, sorted(values1, key=lambda t: t[0])]])
1462
    data_tables_set.append([[['Seulement facturé en traitement'], [[len(values2)]]], [cols, sorted(values2, key=lambda t: t[0])]])
1463
    data_tables_set.append([[['Facturé en diagnostic et en traitement'], [[len(values3)]]], [cols, sorted(values3, key=lambda t: t[0])]])
1464
    return data_tables_set
1465

    
1466
def mises(statistic):
1467
    if not statistic.in_service:
1468
        return None
1469
    if not statistic.in_end_date:
1470
        statistic.in_end_date = datetime.today()
1471
    if not statistic.in_start_date:
1472
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1473
    acts = Act.objects.filter(valide='True',
1474
        date__gte=statistic.in_start_date,
1475
        date__lte=statistic.in_end_date,
1476
        patient__service=statistic.in_service)
1477
    patients = acts.order_by('patient').distinct('patient').\
1478
        values_list('patient')
1479
    patients = PatientRecord.objects.filter(id__in=[patient[0]
1480
        for patient in patients])
1481
    pathologies = dict()
1482
    for patient in patients:
1483
        for pathology in patient.mises_1.all():
1484
            pathologies.setdefault(pathology, 0)
1485
            pathologies[pathology] += 1
1486
        for pathology in patient.mises_2.all():
1487
            pathologies.setdefault(pathology, 0)
1488
            pathologies[pathology] += 1
1489
        for pathology in patient.mises_3.all():
1490
            pathologies.setdefault(pathology, 0)
1491
            pathologies[pathology] += 1
1492
    data = [['Pathologies MISES', 'Nombre de patients concernés']]
1493
    data.append(OrderedDict(sorted(pathologies.items(), key=lambda t: t[0].ordering_code)).items())
1494
    return [[data]]
1495

    
1496
def deficiencies(statistic):
1497
    if not statistic.in_service:
1498
        return None
1499
    if not statistic.in_end_date:
1500
        statistic.in_end_date = datetime.today()
1501
    if not statistic.in_start_date:
1502
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1503
    acts = Act.objects.filter(valide='True',
1504
        date__gte=statistic.in_start_date,
1505
        date__lte=statistic.in_end_date,
1506
        patient__service=statistic.in_service)
1507
    patients = acts.order_by('patient').distinct('patient').\
1508
        values_list('patient')
1509
    patients = PatientRecord.objects.filter(id__in=[patient[0]
1510
        for patient in patients])
1511
    deficiencies_three = ('deficiency_intellectual',
1512
            'deficiency_autism_and_other_ted',
1513
            'deficiency_mental_disorder', 'deficiency_learning_disorder',
1514
            'deficiency_auditory', 'deficiency_visual', 'deficiency_motor',
1515
            'deficiency_metabolic_disorder', 'deficiency_brain_damage',
1516
            'deficiency_behavioral_disorder', 'deficiency_other_disorder')
1517
    data = [['Déficiences', 'Nombre de patients concernés'], []]
1518
    for deficiency in deficiencies_three:
1519
        name = PatientRecord._meta.get_field_by_name(deficiency)[0].verbose_name
1520
        filter_dict = {deficiency: 1}
1521
        data[1].append((name + ' à titre principal', patients.filter(**filter_dict).count()))
1522
        filter_dict = {deficiency: 2}
1523
        data[1].append((name + ' à titre associé', patients.filter(**filter_dict).count()))
1524
    name = PatientRecord._meta.get_field_by_name('deficiency_polyhandicap')[0].verbose_name
1525
    data[1].append((name, patients.filter(deficiency_polyhandicap=True).count()))
1526
    name = PatientRecord._meta.get_field_by_name('deficiency_in_diagnostic')[0].verbose_name
1527
    data[1].append((name, patients.filter(deficiency_in_diagnostic=True).count()))
1528
    return [[data]]
1529

    
1530
class Statistic(models.Model):
1531
    patients = models.ManyToManyField('dossiers.PatientRecord',
1532
            null=True, blank=True, default=None)
1533
    participants = models.ManyToManyField('personnes.People',
1534
            null=True, blank=True, default=None)
1535
    in_start_date = None
1536
    in_end_date = None
1537
    in_service = None
1538
    in_participants = None
1539
    in_patients = None
1540
    in_year = None
1541
    inscriptions = False
1542

    
1543
    def __init__(self, name=None, inputs=dict()):
1544
        self.name = name
1545
        params = STATISTICS.get(name, {})
1546
        self.display_name = params['display_name']
1547
        self.category = params['category']
1548
        self.inputs = inputs
1549
        self.in_participants = list()
1550
        participants = inputs.get('participants')
1551
        if participants:
1552
            p_str_ids = [p for p in participants.split('|') if p]
1553
            for str_id in p_str_ids:
1554
                try:
1555
                    self.in_participants.append(Worker.objects.get(pk=int(str_id)))
1556
                except:
1557
                    pass
1558
        self.in_patients = list()
1559
        patients = inputs.get('patients')
1560
        if patients:
1561
            p_str_ids = [p for p in patients.split('|') if p]
1562
            for str_id in p_str_ids:
1563
                try:
1564
                    self.in_patients.append(PatientRecord.objects.get(pk=int(str_id)))
1565
                except:
1566
                    pass
1567
        self.in_service = inputs.get('service')
1568
        self.in_start_date = None
1569
        try:
1570
            self.in_start_date = datetime.strptime(inputs.get('start_date'),
1571
                "%d/%m/%Y")
1572
            self.in_year = self.in_start_date.year
1573
        except:
1574
            pass
1575
        self.in_end_date = None
1576
        try:
1577
            self.in_end_date = datetime.strptime(inputs.get('end_date'),
1578
                "%d/%m/%Y")
1579
        except:
1580
            pass
1581
        self.inscriptions = inputs.get('inscriptions')
1582

    
1583
    def get_data(self):
1584
        func = globals()[self.name]
1585
        data = func(self)
1586
        self.data = [[[["Date du jour", "Service", "Nom statistique"],
1587
            [[formats.date_format(datetime.today(), "SHORT_DATE_FORMAT"),
1588
            self.in_service, STATISTICS[self.name]['display_name']]]]]] + data
1589
        return self.data
1590

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

    
1635
        import codecs
1636
        filename = None
1637
        with tempfile.NamedTemporaryFile(delete=False) as temp_out_csv:
1638
            filename = temp_out_csv.name
1639
            temp_out_csv.close()
1640
        with codecs.open(filename, 'w+b', encoding=encoding) as encoded_f:
1641
            try:
1642
                writer = csv.writer(encoded_f, dialect='csv_profile')
1643
                for data_set in self.data:
1644
                    for data in data_set:
1645
                        writer.writerow(data[0])
1646
                        if len(data) > 1:
1647
                            for d in data[1]:
1648
                                writer.writerow(d)
1649
                        writer.writerow([])
1650
                    writer.writerow([])
1651
                return filename
1652
            except:
1653
                try:
1654
                    os.unlink(temp_out_pdf.name)
1655
                except:
1656
                    pass
1657

    
1658
    def get_file(self):
1659
        self.get_data()
1660
        return self.render_to_csv()
(5-5/8)