Project

General

Profile

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

calebasse / calebasse / statistics / statistics.py @ 6188a681

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': 'Listes des dossiers avec un acte validé, ou un acte '
49
            'proposé seulement, sur une période et triés par état du dossier '
50
            'en fin de période',
51
        'category': 'Patients',
52
        'comment': """Listes des dossiers avec un acte validé ou un acte
53
            proposé seulement sur une période et triés par état du dossier en
54
            fin de période.
55
            La date de début de la plage par
56
            défaut est le 1er janvier de l'année en cours. La date de fin de
57
            la plage par défaut est aujourd'hui.
58
            """
59
    },
60
    'closed_files' :
61
        {
62
        'display_name': 'Dossier clos sur une période et durée de la prise '
63
            'en charge',
64
        'category': 'Patients',
65
        'comment': """Liste des dossiers clos avec leur durée de la prise en
66
            charge sur la plage de dates spécifiée. Le nombre de dossier et la
67
            durée moyenne de la prise en charge est également donnée. La date
68
            de début de la plage par défaut est le 1er janvier de l'année en
69
            cours. La date de fin de la plage par défaut est aujourd'hui.
70
            """
71
    },
72
    'annual_activity' :
73
        {
74
        'display_name': "Activité annuelle",
75
        'category': 'Intervenants',
76
        'comment': """Tableaux de synthèse annuelle. La date saisie
77
            indique l'année à traiter. Si aucune date n'est spécifiée ce sera
78
            l'année en cours. Si aucun intervenant n'est spécifié, les
79
            tableaux de synthèse globaux sont retournés. Si des intervenants
80
            sont indiqués, les tableaux de synthèse pour chaque intervenant
81
            sont retournés.
82
            """
83
    },
84
    'patients_details' :
85
        {
86
        'display_name': "Synthèse par patient",
87
        'category': 'Patients',
88
        'comment': """Tableaux de synthèse par patient. Si aucun patient n'est
89
            indiqué, une synthèse pour chaque patient est retournée. La plage
90
            de date permet de selectionner les patients pour lesquels au
91
            moins au acte a été proposé durant cette période. Si un dossier a
92
            été clos durant cette période mais qu'aucun acte n'a été proposé
93
            durant cette période, il ne sera pas pris en compte. La date de
94
            début de la plage par défaut est le 1er janvier de l'année en
95
            cours. La date de fin de la plage par défaut est aujourd'hui. """
96
    },
97
    'patients_synthesis' :
98
        {
99
        'display_name': 'Synthèse sur les patients avec un acte valide sur '
100
            'la plage de date',
101
        'category': 'Patients',
102
        'comment': """Patients ayant eu au moins un acte validé
103
            sur la plage de dates spécifiée. La date de début de la plage par
104
            défaut est le 1er janvier de l'année en cours. La date de fin de
105
            la plage par défaut est aujourd'hui.
106
            """
107
    },
108
    'acts_synthesis' :
109
        {
110
        'display_name': 'Synthèse sur les actes',
111
        'category': 'Actes',
112
        'comment': """Synthèse sur les actes
113
            sur la plage de dates spécifiée. La date de début de la plage par
114
            défaut est le 1er janvier de l'année en cours. La date de fin de
115
            la plage par défaut est aujourd'hui.
116
            """
117
    },
118
    'acts_synthesis_cmpp' :
119
        {
120
        'display_name': 'Synthèse sur les dossiers facturés au CMPP',
121
        'category': 'Patients',
122
        'services': ['CMPP', ],
123
        'comment': """Synthèse sur les dossiers facturés au CMPP selon que ce
124
            soit en diagnostic, en traitement ou les deux,
125
            sur la plage de dates spécifiée. La date de début de la plage par
126
            défaut est le 1er janvier de l'année en cours. La date de fin de
127
            la plage par défaut est aujourd'hui.
128
            """
129
    },
130
    'mises' :
131
        {
132
        'display_name': 'Synthèse sur les pathologies MISES',
133
        'category': 'Patients',
134
        'comment': """Synthèse sur les pathologies
135
            sur la plage de dates spécifiée. La date de début de la plage par
136
            défaut est le 1er janvier de l'année en cours. La date de fin de
137
            la plage par défaut est aujourd'hui.
138
            """
139
    },
140
    'deficiencies' :
141
        {
142
        'display_name': 'Synthèse sur les déficiences',
143
        'category': 'Patients',
144
        'comment': """Synthèse sur les déficiences
145
            sur la plage de dates spécifiée. La date de début de la plage par
146
            défaut est le 1er janvier de l'année en cours. La date de fin de
147
            la plage par défaut est aujourd'hui.
148
            """
149
    },
150
    'patients_protection' :
151
        {
152
        'display_name': 'Synthèse sur les mesures de protection des patients '
153
            'à une date donnée',
154
        'category': 'Patients',
155
        'comment': """La date par défaut est aujourd'hui.
156
            """
157
    },
158
}
159

    
160
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']
161

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

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

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

    
268
    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
269
    analyses[key][i+trim_cnt].pointe = analyses[key][i+trim_cnt].total - analyses[key][i+trim_cnt].non_pointe
270
    percent_abs = 100
271
    if not analyses[key][i+trim_cnt].pointe or not analyses[key][i+trim_cnt].absent:
272
        percent_abs = 0
273
    elif analyses[key][i+trim_cnt].absent:
274
        percent_abs = (analyses[key][i+trim_cnt].absent/float(analyses[key][i+trim_cnt].pointe))*100
275
    analyses[key][i+trim_cnt].percent_abs = "%.2f" % percent_abs
276

    
277
    if statistic.in_service.name == 'CMPP':
278
        analyses[key][i+trim_cnt].facturables = analyses[key][i+trim_cnt].acts_present - analyses[key][i+trim_cnt].non_facturables
279
        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
280
        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
281
        percent_nf = 100
282
        if not analyses[key][i+trim_cnt].pointe or not analyses[key][i+trim_cnt].nf:
283
            percent_nf = 0
284
        elif analyses[key][i+trim_cnt].nf:
285
            percent_nf = (analyses[key][i+trim_cnt].nf/float(analyses[key][i+trim_cnt].pointe))*100
286
        analyses[key][i+trim_cnt].percent_nf = "%.2f" % percent_nf
287
        if analyses[key][i+trim_cnt].days:
288
            analyses[key][i+trim_cnt].fact_per_day = "%.2f" % (analyses[key][i+trim_cnt].really_facturables / float(analyses[key][i+trim_cnt].days))
289

    
290
    if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].intervenants:
291
        analyses[key][i+trim_cnt].moving_time_per_intervene = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].intervenants
292
    if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].acts_present:
293
        analyses[key][i+trim_cnt].moving_time_per_act = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].acts_present
294

    
295

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

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

    
401
def strfdelta(tdelta, fmt):
402
    if not tdelta:
403
        return '0'
404
    d = {"days": tdelta.days}
405
    d["hours"], rem = divmod(tdelta.seconds, 3600)
406
    d["minutes"], d["seconds"] = divmod(rem, 60)
407
    return fmt.format(**d)
408

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

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

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

    
584
def run_annual_activity(statistic, start_day, analyses, key, label, data_tables, participant=None):
585
    analyses[key] = list()
586
    trim_cnt = 0
587
    for i in range(0, 12):
588
        annual_activity_month_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant)
589
        if not (i + 1) % 3:
590
            trim_cnt += 1
591
            annual_activity_trimester_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant)
592
    end_day = datetime(start_day.year+1, 1, 1)
593
    annual_activity_synthesis_analysis(statistic, start_day, end_day, analyses, key, participant)
594
    annual_activity_build_tables(statistic, analyses, key, label, data_tables)
595

    
596
def annual_activity(statistic):
597
    if not statistic.in_service:
598
        return None
599
    start_day = datetime(datetime.today().year, 1, 1)
600
    if statistic.in_year:
601
        start_day = datetime(statistic.in_year, 1, 1)
602
    data_tables = list()
603
    analyses = dict()
604
    if not statistic.in_participants:
605
        run_annual_activity(statistic, start_day, analyses, 'global', str(statistic.in_year) + ' - Tous', data_tables, participant=None)
606
    else:
607
        for participant in statistic.in_participants:
608
            run_annual_activity(statistic, start_day, analyses, participant.id, str(statistic.in_year) + ' - ' + str(participant), data_tables, participant=participant)
609
    return [data_tables]
610

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

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

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

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

    
737
    data_tables_set = []
738
    data_tables = []
739
    data = []
740
    data.append(['Période', 'Jours'])
741
    data.append([("%s - %s"
742
        % (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
743
        formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
744
        (statistic.in_end_date-statistic.in_start_date).days+1)])
745
    data_tables.append(data)
746
    data_tables_set.append(data_tables)
747

    
748
    acts_base = Act.objects.filter(
749
        date__gte=statistic.in_start_date,
750
        date__lte=statistic.in_end_date,
751
        patient__service=statistic.in_service)
752
    acts_valide = acts_base.filter(valide=True)
753
    acts_valide_patients_ids = acts_valide.order_by('patient').\
754
        distinct('patient').values_list('patient')
755
    acts_valide_patients = PatientRecord.objects.filter(
756
        id__in=[patient[0] for patient in acts_valide_patients_ids])
757
    all_patients_ids = acts_base.order_by('patient').distinct('patient').\
758
        values_list('patient')
759
    acts_not_valide_patients = PatientRecord.objects.filter(
760
        id__in=[patient[0] for patient in all_patients_ids
761
            if not patient in acts_valide_patients_ids])
762

    
763
    data_tables_set.append(process(acts_valide_patients, "Patients avec un acte validé sur la période"))
764
    p_val = dict()
765
    for p in acts_valide_patients:
766
        p_val.setdefault(p.get_state_at_day(statistic.in_end_date).status, []).append(p)
767
    for k, v in p_val.items():
768
        data_tables_set.append(process(v, "Patients avec un acte validé et dans l'état '%s' en date du %s" % (k, formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT"))))
769
    p_val = dict()
770
    data_tables_set.append(process(acts_not_valide_patients, "Patients avec un acte proposé seulement sur la période"))
771
    for p in acts_not_valide_patients:
772
        p_val.setdefault(p.get_state_at_day(statistic.in_end_date).status, []).append(p)
773
    for k, v in p_val.items():
774
        data_tables_set.append(process(v, "Patients avec sans acte validé et dans l'état '%s' en date du %s" % (k, formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT"))))
775

    
776
    return data_tables_set
777

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

    
835
    days_states = {}
836
    for record in closed_records:
837
        for state, duration in record.get_states_history_with_duration():
838
            days_states.setdefault(state.status, 0)
839
            days_states[state.status] += duration.days
840
    data = []
841
    data.append(["Etat des dossiers", "Nombre de jours total", "Nombre de jours moyen par dossier"])
842
    values = []
843
    for status, duration in days_states.iteritems():
844
        values.append((status.name, duration, duration/closed_records.count()))
845
    data.append(values)
846
    data_tables.append(data)
847
    return [data_tables]
848

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

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

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

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

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

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

    
987
    return data_tables_set
988

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

    
1010
    active_states = None
1011
    if statistic.in_service.name == 'CMPP':
1012
        active_states = ('TRAITEMENT', 'DIAGNOSTIC', )
1013
    elif statistic.in_service.name == 'CAMSP':
1014
        active_states = ('SUIVI', 'BILAN', 'SURVEILLANCE', 'CLOS', )
1015
    else:
1016
        active_states = ('TRAITEMENT', )
1017

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

    
1027
        # Patient has been in treatment
1028
        # We look for all the treament periods during the selected dates
1029
        # A treament period ends if during the period the file has left treament state
1030
        openings = []
1031
        opening = []
1032
        start = False
1033
        for ts in traitement_states:
1034
            if start:
1035
                openings.append(opening)
1036
                opening = []
1037
                start = False
1038
            if ts.get_next_state() and not ts.get_next_state().status.type in active_states and ts.get_next_state().get_next_state() and ts.get_next_state().get_next_state().status.type in active_states:
1039
                start = True
1040
            opening.append(ts)
1041
        openings.append(opening)
1042

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

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

    
1068
    if statistic.inscriptions:
1069
        patients = PatientRecord.objects.filter(id__in=[p.id for p, _, _, _, _ in inscriptions])
1070
        acts = acts.filter(patient__in=patients)
1071

    
1072
    nb_patients = patients.count()
1073
    if not nb_patients:
1074
        return []
1075

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

    
1094
    data = []
1095
    data.append(["Etat du dossier à ce jour (%s)" % formats.date_format(datetime.today(), "SHORT_DATE_FORMAT"), 'Nombre de patients'])
1096
    states = dict()
1097
    for patient in patients:
1098
        states.setdefault(patient.get_current_state().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(["Etat du dossier en date de fin (%s)" % formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT"), 'Nombre de patients'])
1107
    states = dict()
1108
    for patient in patients:
1109
        states.setdefault(patient.get_state_at_day(statistic.in_end_date).status, []).append(patient)
1110
    values = []
1111
    for state, ps in states.iteritems():
1112
        values.append((state.name, len(ps)))
1113
    data.append(values)
1114
    data_tables.append(data)
1115

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

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

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

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

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

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

    
1188

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

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

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

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

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

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

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

    
1336
    return [data_tables]
1337

    
1338
def acts_synthesis(statistic):
1339
    if not statistic.in_service:
1340
        return None
1341
    if not statistic.in_end_date:
1342
        statistic.in_end_date = datetime.today()
1343
    if not statistic.in_start_date:
1344
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1345

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

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

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

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

    
1429
    return data_tables_set
1430

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

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

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

    
1529
class Statistic(object):
1530
    in_start_date = None
1531
    in_end_date = None
1532
    in_service = None
1533
    in_participants = None
1534
    in_patients = None
1535
    in_year = None
1536
    inscriptions = False
1537

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

    
1578
    def get_data(self):
1579
        func = globals()[self.name]
1580
        data = func(self)
1581
        self.data = [[[["Date du jour", "Service", "Nom statistique"],
1582
            [[formats.date_format(datetime.today(), "SHORT_DATE_FORMAT"),
1583
            self.in_service, STATISTICS[self.name]['display_name']]]]]] + data
1584
        return self.data
1585

    
1586
    def render_to_csv(self):
1587
        _delimiter = ';'
1588
        _quotechar = '|'
1589
        _doublequote = True
1590
        _skipinitialspace = False
1591
        _lineterminator = '\r\n'
1592
        _quoting = csv.QUOTE_MINIMAL
1593
        if getattr(settings, 'CSVPROFILE', None):
1594
            csv_profile = settings.CSVPROFILE
1595
            _delimiter = csv_profile.get('delimiter', ';')
1596
            _quotechar = csv_profile.get('quotechar', '|')
1597
            _doublequote = csv_profile.get('doublequote', True)
1598
            _skipinitialspace = csv_profile.get('skipinitialspace', False)
1599
            _lineterminator = csv_profile.get('lineterminator', '\r\n')
1600
            _quoting = csv_profile.get('quoting', csv.QUOTE_MINIMAL)
1601
        class CSVProfile(csv.Dialect):
1602
            delimiter = _delimiter
1603
            quotechar = _quotechar
1604
            doublequote = _doublequote
1605
            skipinitialspace = _skipinitialspace
1606
            lineterminator = _lineterminator
1607
            quoting = _quoting
1608
        csv.register_dialect('csv_profile', CSVProfile())
1609
        encoding = getattr(settings, 'CSV_ENCODING', 'utf-8')
1610

    
1611
        import codecs
1612
        filename = None
1613
        with tempfile.NamedTemporaryFile(delete=False) as temp_out_csv:
1614
            filename = temp_out_csv.name
1615
            temp_out_csv.close()
1616
        with codecs.open(filename, 'w+b', encoding=encoding) as encoded_f:
1617
            try:
1618
                writer = csv.writer(encoded_f, 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 filename
1628
            except:
1629
                try:
1630
                    os.unlink(temp_out_pdf.name)
1631
                except:
1632
                    pass
1633

    
1634
    def get_file(self):
1635
        self.get_data()
1636
        return self.render_to_csv()
(5-5/8)