Project

General

Profile

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

calebasse / calebasse / statistics / statistics.py @ 86aa738f

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
    active_states = None
1022
    if statistic.in_service.name == 'CMPP':
1023
        active_states = ('TRAITEMENT', 'DIAGNOSTIC', )
1024
    elif statistic.in_service.name == 'CAMSP':
1025
        active_states = ('SUIVI', 'BILAN', 'CLOS', )
1026
    else:
1027
        active_states = ('TRAITEMENT', )
1028

    
1029
    inscriptions = []
1030
    for patient in patients:
1031
        # Select patient if she has been in treament between the selected dates
1032
        traitement_states_tmp = FileState.objects.filter(patient=patient, status__type__in=active_states, date_selected__lte=statistic.in_end_date).order_by('date_selected')
1033
        traitement_states = []
1034
        for ts in traitement_states_tmp:
1035
            if not ts.get_next_state() or ts.get_next_state().date_selected >= statistic.in_start_date:
1036
                traitement_states.append(ts)
1037

    
1038
        # Patient has been in treatment
1039
        # We look for all the treament periods during the selected dates
1040
        # A treament period ends if during the period the file has left treament state
1041
        openings = []
1042
        opening = []
1043
        start = False
1044
        for ts in traitement_states:
1045
            if start:
1046
                openings.append(opening)
1047
                opening = []
1048
                start = False
1049
            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:
1050
                start = True
1051
            opening.append(ts)
1052
        openings.append(opening)
1053

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

    
1068
        # We look to the first act after the datebeginning
1069
        for contact, first_ts in first_tss:
1070
            acts_tmp = Act.objects.filter(valide=True,
1071
                date__gte=first_ts.date_selected,
1072
                patient=patient).order_by('date')
1073
            if acts_tmp and acts_tmp[0].date >= statistic.in_start_date.date() and acts_tmp[0].date <= statistic.in_end_date.date():
1074
                waiting_duration = 0
1075
                if contact:
1076
                    waiting_duration = (acts_tmp[0].date - contact).days
1077
                inscriptions.append((patient, contact, first_ts.date_selected.date(), acts_tmp[0].date, waiting_duration))
1078

    
1079
    if statistic.inscriptions:
1080
        patients = PatientRecord.objects.filter(id__in=[p.id for p, _, _, _, _ in inscriptions])
1081
        acts = acts.filter(patient__in=patients)
1082

    
1083
    nb_patients = patients.count()
1084

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

    
1103
    data = []
1104
    data.append(["Etat du dossier à ce jour (%s)" % formats.date_format(datetime.today(), "SHORT_DATE_FORMAT"), 'Nombre de patients'])
1105
    states = dict()
1106
    for patient in patients:
1107
        states.setdefault(patient.get_current_state().status, []).append(patient)
1108
    values = []
1109
    for state, ps in states.iteritems():
1110
        values.append((state.name, len(ps)))
1111
    data.append(values)
1112
    data_tables.append(data)
1113

    
1114
    data = []
1115
    data.append(["Etat du dossier en date de fin (%s)" % formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT"), 'Nombre de patients'])
1116
    states = dict()
1117
    for patient in patients:
1118
        states.setdefault(patient.get_state_at_day(statistic.in_end_date).status, []).append(patient)
1119
    values = []
1120
    for state, ps in states.iteritems():
1121
        values.append((state.name, len(ps)))
1122
    data.append(values)
1123
    data_tables.append(data)
1124

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

    
1130
    if inscriptions:
1131
        data = []
1132
        data.append(['Nom', 'Prénom', "Numéro papier", "Date premier acte", "Date passage en traitement", "Date de contact", "Attente"])
1133
        values = []
1134
        for patient, contact, first_ts, first_act, waiting_duration in sorted(inscriptions, key=lambda p: (p[0].last_name, p[0].first_name)):
1135
            values.append((patient.last_name, patient.first_name, patient.paper_id, first_act, first_ts, contact, waiting_duration))
1136
        data.append(values)
1137
        data_tables.append(data)
1138

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

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

    
1174
    birth_years = dict()
1175
    patients_without_birthyear = []
1176
    for patient in patients:
1177
        try:
1178
            birth_years.setdefault(patient.birthdate.year, []).append(patient)
1179
        except:
1180
            patients_without_birthyear.append(patient)
1181
    data = []
1182
    data.append(['Année de naissance', "Nombre de dossiers", "%"])
1183
    values = []
1184
    for birth_year, pts in birth_years.iteritems():
1185
        values.append((birth_year, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1186
    values.append(('Non renseignée',  len(patients_without_birthyear), "%.2f" % (len(patients_without_birthyear) / float(len(patients)) * 100)))
1187
    data.append(values)
1188
    data_tables.append(data)
1189

    
1190
    if patients_without_birthyear:
1191
        data = []
1192
        data.append(["Patients sans date de naissance"])
1193
        values = [[patients_without_birthyear]]
1194
        data.append(values)
1195
        data_tables.append(data)
1196

    
1197

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

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

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

    
1281
    provenances = dict()
1282
    unknown = 0
1283
    for patient in patients:
1284
        if patient.provenance:
1285
            provenances.setdefault(patient.provenance, []).append(patient)
1286
        else:
1287
            unknown += 1
1288
    data = []
1289
    data.append(["Provenances", "Nombre de dossiers", "%"])
1290
    values = []
1291
    for provenance, pts in provenances.iteritems():
1292
        values.append((provenance, len(pts), "%.2f" % (len(pts) / float(len(patients)) * 100)))
1293
    values.append(('Non renseignée', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1294
    data.append(values)
1295
    data_tables.append(data)
1296

    
1297
    outmotives = dict()
1298
    unknown = 0
1299
    for patient in patients:
1300
        if patient.outmotive:
1301
            outmotives.setdefault(patient.outmotive, []).append(patient)
1302
        else:
1303
            unknown += 1
1304
    data = []
1305
    data.append(["Motifs de sortie", "Nombre de dossiers", "%"])
1306
    values = []
1307
    for outmotive, pts in outmotives.iteritems():
1308
        values.append((outmotive, len(pts)))
1309
    values.append(('Non renseigné', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1310
    data.append(values)
1311
    data_tables.append(data)
1312

    
1313
    outtos = dict()
1314
    unknown = 0
1315
    for patient in patients:
1316
        if patient.outto:
1317
            outtos.setdefault(patient.outto, []).append(patient)
1318
        else:
1319
            unknown += 1
1320
    data = []
1321
    data.append(["Orientations", "Nombre de dossiers", "%"])
1322
    values = []
1323
    for outto, pts in outtos.iteritems():
1324
        values.append((outto, len(pts)))
1325
    values.append(('Non renseigné', unknown, "%.2f" % (unknown / float(len(patients)) * 100)))
1326
    data.append(values)
1327
    data_tables.append(data)
1328

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

    
1345
    return [data_tables]
1346

    
1347
def acts_synthesis(statistic):
1348
    if not statistic.in_service:
1349
        return None
1350
    if not statistic.in_end_date:
1351
        statistic.in_end_date = datetime.today()
1352
    if not statistic.in_start_date:
1353
        statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
1354

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

    
1378
    data_tables=[]
1379
    acts_types = dict()
1380
    for act in acts:
1381
        acts_types.setdefault(act.act_type, []).append(act)
1382
    data = []
1383
    data.append(["Types des actes", "Nombre d'actes proposés", "Nombre de dossiers", "Nombre d'actes réalisés", "Nombre de dossiers"])
1384
    values = []
1385
    for act_type, acts in sorted(acts_types.items(), key=lambda t: t[0].name):
1386
        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()]))))
1387
    data.append(values)
1388
    data_tables.append(data)
1389
    data_tables_set.append(data_tables)
1390

    
1391
    data_tables=[]
1392
    acts_count_participants = dict()
1393
    for act in acts_present:
1394
        acts_count_participants.setdefault(act.doctors.count(), []).append(act)
1395
    data = []
1396
    data.append(["Nombre d'intervenants des actes réalisés", "Nombre d'actes", "Nombre de dossiers concernés"])
1397
    values = []
1398
    for number, acts_counted in acts_count_participants.iteritems():
1399
        values.append((number, len(acts_counted), len(set([a.patient.id for a in acts_counted]))))
1400
    data.append(values)
1401
    data_tables.append(data)
1402
    data_tables_set.append(data_tables)
1403

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

    
1438
    return data_tables_set
1439

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

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

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

    
1538
class Statistic(models.Model):
1539
    patients = models.ManyToManyField('dossiers.PatientRecord',
1540
            null=True, blank=True, default=None)
1541
    participants = models.ManyToManyField('personnes.People',
1542
            null=True, blank=True, default=None)
1543
    in_start_date = None
1544
    in_end_date = None
1545
    in_service = None
1546
    in_participants = None
1547
    in_patients = None
1548
    in_year = None
1549
    inscriptions = False
1550

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

    
1591
    def get_data(self):
1592
        func = globals()[self.name]
1593
        data = func(self)
1594
        self.data = [[[["Date du jour", "Service", "Nom statistique"],
1595
            [[formats.date_format(datetime.today(), "SHORT_DATE_FORMAT"),
1596
            self.in_service, STATISTICS[self.name]['display_name']]]]]] + data
1597
        return self.data
1598

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

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

    
1666
    def get_file(self):
1667
        self.get_data()
1668
        return self.render_to_csv()
(5-5/8)