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
|
}
|
149
|
|
150
|
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']
|
151
|
|
152
|
ANNUAL_ACTIVITY_COLUMN_LABELS = ['Janv', 'Fév', 'Mar', 'T1', 'Avr', 'Mai', 'Jui', 'T2', 'Jui', 'Aoû', 'Sep', 'T3', 'Oct', 'Nov', 'Déc', 'T4', 'Total']
|
153
|
|
154
|
class AnnualActivityProcessingColumn():
|
155
|
total = 0
|
156
|
pointe = 0
|
157
|
non_pointe = 0
|
158
|
absent = 0
|
159
|
percent_abs = 0
|
160
|
reporte = 0
|
161
|
acts_present = 0
|
162
|
abs_non_exc = 0
|
163
|
abs_exc = 0
|
164
|
abs_inter = 0
|
165
|
annul_nous = 0
|
166
|
annul_famille = 0
|
167
|
abs_ess_pps = 0
|
168
|
enf_hosp = 0
|
169
|
non_facturables = 0
|
170
|
facturables = 0
|
171
|
perdus = 0
|
172
|
doubles = 0
|
173
|
really_facturables = 0
|
174
|
factures = 0
|
175
|
diag = 0
|
176
|
trait = 0
|
177
|
restants_a_fac = 0
|
178
|
refac = 0
|
179
|
nf = 0
|
180
|
percent_nf = 0
|
181
|
patients = 0
|
182
|
intervenants = 0
|
183
|
days = 0
|
184
|
fact_per_day = 0
|
185
|
moving_time = timedelta()
|
186
|
moving_time_per_intervene = timedelta()
|
187
|
moving_time_per_act = timedelta()
|
188
|
|
189
|
def annual_activity_month_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant=None):
|
190
|
rd = relativedelta(months=1)
|
191
|
sd = start_day + i * rd
|
192
|
ed = sd + rd
|
193
|
acts = None
|
194
|
moving_events = None
|
195
|
if participant:
|
196
|
acts = Act.objects.filter(date__gte=sd.date(),
|
197
|
date__lt=ed.date(), patient__service=statistic.in_service,
|
198
|
doctors__in=[participant])
|
199
|
moving_events = Event.objects.filter(event_type__label='Temps de trajet',
|
200
|
start_datetime__gte=sd, end_datetime__lt=ed,
|
201
|
services__in=[statistic.in_service],
|
202
|
participants__in=[participant])
|
203
|
else:
|
204
|
acts = Act.objects.filter(date__gte=sd.date(),
|
205
|
date__lt=ed.date(), patient__service=statistic.in_service)
|
206
|
moving_events = Event.objects.filter(event_type__label='Temps de trajet',
|
207
|
start_datetime__gte=sd, end_datetime__lt=ed,
|
208
|
services__in=[statistic.in_service])
|
209
|
analyses[key].append(AnnualActivityProcessingColumn())
|
210
|
analyses[key][i+trim_cnt].patients = acts.aggregate(Count('patient', distinct=True))['patient__count']
|
211
|
analyses[key][i+trim_cnt].intervenants = acts.aggregate(Count('doctors', distinct=True))['doctors__count']
|
212
|
analyses[key][i+trim_cnt].days = acts.aggregate(Count('date', distinct=True))['date__count']
|
213
|
for me in moving_events:
|
214
|
analyses[key][i+trim_cnt].moving_time += me.timedelta()
|
215
|
for a in acts:
|
216
|
if a.is_new():
|
217
|
analyses[key][i+trim_cnt].non_pointe += 1
|
218
|
elif a.is_absent():
|
219
|
state = a.get_state()
|
220
|
if state.state_name == 'REPORTE':
|
221
|
analyses[key][i+trim_cnt].reporte += 1
|
222
|
else:
|
223
|
analyses[key][i+trim_cnt].absent += 1
|
224
|
if state.state_name == 'ABS_NON_EXC':
|
225
|
analyses[key][i+trim_cnt].abs_non_exc += 1
|
226
|
elif state.state_name == 'ABS_EXC':
|
227
|
analyses[key][i+trim_cnt].abs_exc += 1
|
228
|
elif state.state_name == 'ABS_INTER':
|
229
|
analyses[key][i+trim_cnt].abs_inter += 1
|
230
|
elif state.state_name == 'ANNUL_NOUS':
|
231
|
analyses[key][i+trim_cnt].annul_nous += 1
|
232
|
elif state.state_name == 'ANNUL_FAMILLE':
|
233
|
analyses[key][i+trim_cnt].annul_famille += 1
|
234
|
elif state.state_name == 'ABS_ESS_PPS':
|
235
|
analyses[key][i+trim_cnt].abs_ess_pps += 1
|
236
|
elif state.state_name == 'ENF_HOSP':
|
237
|
analyses[key][i+trim_cnt].enf_hosp += 1
|
238
|
else:
|
239
|
analyses[key][i+trim_cnt].acts_present += 1
|
240
|
if statistic.in_service.name == 'CMPP':
|
241
|
if not a.is_billable():
|
242
|
analyses[key][i+trim_cnt].non_facturables += 1
|
243
|
elif a.is_lost:
|
244
|
analyses[key][i+trim_cnt].perdus += 1
|
245
|
elif a.get_state().state_name == 'ACT_DOUBLE':
|
246
|
analyses[key][i+trim_cnt].doubles += 1
|
247
|
elif a.is_billed:
|
248
|
analyses[key][i+trim_cnt].factures += 1
|
249
|
if a.invoice_set.latest('created').first_tag[0] == 'D':
|
250
|
analyses[key][i+trim_cnt].diag += 1
|
251
|
else:
|
252
|
analyses[key][i+trim_cnt].trait += 1
|
253
|
else:
|
254
|
analyses[key][i+trim_cnt].restants_a_fac += 1
|
255
|
if a.invoice_set.all():
|
256
|
analyses[key][i+trim_cnt].refac += 1
|
257
|
|
258
|
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
|
259
|
analyses[key][i+trim_cnt].pointe = analyses[key][i+trim_cnt].total - analyses[key][i+trim_cnt].non_pointe
|
260
|
percent_abs = 100
|
261
|
if not analyses[key][i+trim_cnt].pointe or not analyses[key][i+trim_cnt].absent:
|
262
|
percent_abs = 0
|
263
|
elif analyses[key][i+trim_cnt].absent:
|
264
|
percent_abs = (analyses[key][i+trim_cnt].absent/float(analyses[key][i+trim_cnt].pointe))*100
|
265
|
analyses[key][i+trim_cnt].percent_abs = "%.2f" % percent_abs
|
266
|
|
267
|
if statistic.in_service.name == 'CMPP':
|
268
|
analyses[key][i+trim_cnt].facturables = analyses[key][i+trim_cnt].acts_present - analyses[key][i+trim_cnt].non_facturables
|
269
|
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
|
270
|
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
|
271
|
percent_nf = 100
|
272
|
if not analyses[key][i+trim_cnt].pointe or not analyses[key][i+trim_cnt].nf:
|
273
|
percent_nf = 0
|
274
|
elif analyses[key][i+trim_cnt].nf:
|
275
|
percent_nf = (analyses[key][i+trim_cnt].nf/float(analyses[key][i+trim_cnt].pointe))*100
|
276
|
analyses[key][i+trim_cnt].percent_nf = "%.2f" % percent_nf
|
277
|
if analyses[key][i+trim_cnt].days:
|
278
|
analyses[key][i+trim_cnt].fact_per_day = "%.2f" % (analyses[key][i+trim_cnt].really_facturables / float(analyses[key][i+trim_cnt].days))
|
279
|
|
280
|
if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].intervenants:
|
281
|
analyses[key][i+trim_cnt].moving_time_per_intervene = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].intervenants
|
282
|
if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].acts_present:
|
283
|
analyses[key][i+trim_cnt].moving_time_per_act = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].acts_present
|
284
|
|
285
|
|
286
|
def annual_activity_trimester_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant=None):
|
287
|
analyses[key].append(AnnualActivityProcessingColumn())
|
288
|
rd = relativedelta(months=1)
|
289
|
sd = start_day + i * rd
|
290
|
start = start_day + (i-2) * rd
|
291
|
end = sd + rd
|
292
|
acts = None
|
293
|
if participant:
|
294
|
acts = Act.objects.filter(date__gte=start.date(),
|
295
|
date__lt=end.date(), patient__service=statistic.in_service,
|
296
|
doctors__in=[participant])
|
297
|
else:
|
298
|
acts = Act.objects.filter(date__gte=start.date(),
|
299
|
date__lt=end.date(), patient__service=statistic.in_service)
|
300
|
for row in ANNUAL_ACTIVITY_ROWS:
|
301
|
if row == 'percent_abs':
|
302
|
pointe = analyses[key][i+trim_cnt-1].pointe + analyses[key][i-2+trim_cnt].pointe + analyses[key][i-3+trim_cnt].pointe
|
303
|
tot_abs = analyses[key][i+trim_cnt-1].absent + analyses[key][i-2+trim_cnt].absent + analyses[key][i-3+trim_cnt].absent
|
304
|
percent_abs = 100
|
305
|
if not pointe or not tot_abs:
|
306
|
percent_abs = 0
|
307
|
elif tot_abs:
|
308
|
percent_abs = (tot_abs/float(pointe))*100
|
309
|
analyses[key][i+trim_cnt].percent_abs = "%.2f" % percent_abs
|
310
|
elif row == 'percent_nf':
|
311
|
pointe = analyses[key][i+trim_cnt-1].pointe + analyses[key][i-2+trim_cnt].pointe + analyses[key][i-3+trim_cnt].pointe
|
312
|
tot_nf = analyses[key][i+trim_cnt-1].nf + analyses[key][i-2+trim_cnt].nf + analyses[key][i-3+trim_cnt].nf
|
313
|
percent_nf = 100
|
314
|
if not pointe or not tot_nf:
|
315
|
percent_nf = 0
|
316
|
elif tot_nf:
|
317
|
percent_nf = (tot_nf/float(pointe))*100
|
318
|
analyses[key][i+trim_cnt].percent_nf = "%.2f" % percent_nf
|
319
|
elif row == 'patients':
|
320
|
analyses[key][i+trim_cnt].patients = acts.aggregate(Count('patient', distinct=True))['patient__count']
|
321
|
elif row == 'intervenants':
|
322
|
analyses[key][i+trim_cnt].intervenants = acts.aggregate(Count('doctors', distinct=True))['doctors__count']
|
323
|
elif row == 'fact_per_day':
|
324
|
if analyses[key][i+trim_cnt].days:
|
325
|
analyses[key][i+trim_cnt].fact_per_day = "%.2f" % (analyses[key][i+trim_cnt].really_facturables / float(analyses[key][i+trim_cnt].days))
|
326
|
elif row == 'moving_time_per_intervene':
|
327
|
if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].intervenants:
|
328
|
analyses[key][i+trim_cnt].moving_time_per_intervene = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].intervenants
|
329
|
elif row == 'moving_time_per_act':
|
330
|
if analyses[key][i+trim_cnt].moving_time and analyses[key][i+trim_cnt].acts_present:
|
331
|
analyses[key][i+trim_cnt].moving_time_per_act = analyses[key][i+trim_cnt].moving_time / analyses[key][i+trim_cnt].acts_present
|
332
|
else:
|
333
|
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))
|
334
|
|
335
|
def annual_activity_synthesis_analysis(statistic, start_day, end_day, analyses, key, participant=None):
|
336
|
analyses[key].append(AnnualActivityProcessingColumn())
|
337
|
acts = None
|
338
|
if participant:
|
339
|
acts = Act.objects.filter(date__gte=start_day.date(),
|
340
|
date__lt=end_day.date(), patient__service=statistic.in_service,
|
341
|
doctors__in=[participant])
|
342
|
else:
|
343
|
acts = Act.objects.filter(date__gte=start_day.date(),
|
344
|
date__lt=end_day.date(), patient__service=statistic.in_service)
|
345
|
for row in ANNUAL_ACTIVITY_ROWS:
|
346
|
if row == 'percent_abs':
|
347
|
tot_abs = 0
|
348
|
pointe = 0
|
349
|
for i in (3, 7, 11, 15):
|
350
|
pointe += analyses[key][i].pointe
|
351
|
tot_abs += analyses[key][i].absent
|
352
|
percent_abs = 100
|
353
|
if not pointe or not tot_abs:
|
354
|
percent_abs = 0
|
355
|
elif tot_abs:
|
356
|
percent_abs = (tot_abs/float(pointe))*100
|
357
|
analyses[key][16].percent_abs = "%.2f" % percent_abs
|
358
|
elif row == 'percent_nf':
|
359
|
tot_nf= 0
|
360
|
pointe = 0
|
361
|
for i in (3, 7, 11, 15):
|
362
|
pointe += analyses[key][i].pointe
|
363
|
tot_nf += analyses[key][i].nf
|
364
|
percent_nf = 100
|
365
|
if not pointe or not tot_nf:
|
366
|
percent_nf = 0
|
367
|
elif tot_nf:
|
368
|
percent_nf = (tot_nf/float(pointe))*100
|
369
|
analyses[key][16].percent_nf = "%.2f" % percent_nf
|
370
|
elif row == 'patients':
|
371
|
analyses[key][16].patients = acts.aggregate(Count('patient', distinct=True))['patient__count']
|
372
|
elif row == 'intervenants':
|
373
|
analyses[key][16].intervenants = acts.aggregate(Count('doctors', distinct=True))['doctors__count']
|
374
|
elif row == 'fact_per_day':
|
375
|
if analyses[key][16].days:
|
376
|
analyses[key][16].fact_per_day = "%.2f" % (analyses[key][16].really_facturables / float(analyses[key][16].days))
|
377
|
elif row == 'moving_time_per_intervene':
|
378
|
if analyses[key][16].moving_time and analyses[key][16].intervenants:
|
379
|
analyses[key][16].moving_time_per_intervene = analyses[key][16].moving_time / analyses[key][16].intervenants
|
380
|
elif row == 'moving_time_per_act':
|
381
|
if analyses[key][16].moving_time and analyses[key][16].acts_present:
|
382
|
analyses[key][16].moving_time_per_act = analyses[key][16].moving_time / analyses[key][16].acts_present
|
383
|
else:
|
384
|
val = 0
|
385
|
if row == 'moving_time':
|
386
|
val = timedelta()
|
387
|
for i in (3, 7, 11, 15):
|
388
|
val += getattr(analyses[key][i], row)
|
389
|
setattr(analyses[key][16], row, val)
|
390
|
|
391
|
def strfdelta(tdelta, fmt):
|
392
|
if not tdelta:
|
393
|
return '0'
|
394
|
d = {"days": tdelta.days}
|
395
|
d["hours"], rem = divmod(tdelta.seconds, 3600)
|
396
|
d["minutes"], d["seconds"] = divmod(rem, 60)
|
397
|
return fmt.format(**d)
|
398
|
|
399
|
def annual_activity_build_tables(statistic, analyses, key, label, data_tables):
|
400
|
table_1 = []
|
401
|
table_1_label = label + ' - général'
|
402
|
table_1.append([table_1_label] + ANNUAL_ACTIVITY_COLUMN_LABELS)
|
403
|
rows = []
|
404
|
row = ['Proposés']
|
405
|
for column in analyses[key]:
|
406
|
row.append(column.total)
|
407
|
rows.append(row)
|
408
|
row = ['Non pointés']
|
409
|
for column in analyses[key]:
|
410
|
row.append(column.non_pointe)
|
411
|
rows.append(row)
|
412
|
row = ['Absences']
|
413
|
for column in analyses[key]:
|
414
|
row.append(column.absent)
|
415
|
rows.append(row)
|
416
|
row = ['Reportés']
|
417
|
for column in analyses[key]:
|
418
|
row.append(column.reporte)
|
419
|
rows.append(row)
|
420
|
row = ['Présents']
|
421
|
for column in analyses[key]:
|
422
|
row.append(column.acts_present)
|
423
|
rows.append(row)
|
424
|
if statistic.in_service.name == 'CMPP':
|
425
|
row = ['Facturables']
|
426
|
for column in analyses[key]:
|
427
|
row.append(column.really_facturables)
|
428
|
rows.append(row)
|
429
|
row = ['Facturés']
|
430
|
for column in analyses[key]:
|
431
|
row.append(column.factures)
|
432
|
rows.append(row)
|
433
|
row = ['Diagnostics']
|
434
|
for column in analyses[key]:
|
435
|
row.append(column.diag)
|
436
|
rows.append(row)
|
437
|
row = ['Traitements']
|
438
|
for column in analyses[key]:
|
439
|
row.append(column.trait)
|
440
|
rows.append(row)
|
441
|
row = ['Restants à facturer']
|
442
|
for column in analyses[key]:
|
443
|
row.append(column.restants_a_fac)
|
444
|
rows.append(row)
|
445
|
row = ['Dont en refact.']
|
446
|
for column in analyses[key]:
|
447
|
row.append(column.refac)
|
448
|
rows.append(row)
|
449
|
row = ['Patients']
|
450
|
for column in analyses[key]:
|
451
|
row.append(column.patients)
|
452
|
rows.append(row)
|
453
|
row = ['Intervenants']
|
454
|
for column in analyses[key]:
|
455
|
row.append(column.intervenants)
|
456
|
rows.append(row)
|
457
|
row = ['Jours']
|
458
|
for column in analyses[key]:
|
459
|
row.append(column.days)
|
460
|
rows.append(row)
|
461
|
if statistic.in_service.name == 'CMPP':
|
462
|
row = ['Facturables / jour']
|
463
|
for column in analyses[key]:
|
464
|
row.append(column.fact_per_day)
|
465
|
rows.append(row)
|
466
|
row = ['Temps de déplacement']
|
467
|
for column in analyses[key]:
|
468
|
row.append(strfdelta(column.moving_time, "{hours}h {minutes}m"))
|
469
|
if column.moving_time.days:
|
470
|
row.append(strfdelta(column.moving_time, "{days}j {hours}h {minutes}m"))
|
471
|
rows.append(row)
|
472
|
row = ['Temps de déplacement par intervenant']
|
473
|
for column in analyses[key]:
|
474
|
row.append(strfdelta(column.moving_time_per_intervene, "{hours}h {minutes}m"))
|
475
|
if column.moving_time_per_intervene.days:
|
476
|
row.append(strfdelta(column.moving_time_per_intervene, "{days}j {hours}h {minutes}m"))
|
477
|
rows.append(row)
|
478
|
row = ['Temps de déplacement par acte']
|
479
|
for column in analyses[key]:
|
480
|
row.append(strfdelta(column.moving_time_per_act, "{hours}h {minutes}m"))
|
481
|
if column.moving_time_per_act.days:
|
482
|
row.append(strfdelta(column.moving_time_per_act, "{days}j {hours}h {minutes}m"))
|
483
|
rows.append(row)
|
484
|
table_1.append(rows)
|
485
|
data_tables.append(table_1)
|
486
|
|
487
|
table_2 = []
|
488
|
table_2_label = label + ' - absences'
|
489
|
table_2.append([table_2_label] + ANNUAL_ACTIVITY_COLUMN_LABELS)
|
490
|
rows = []
|
491
|
row = ['Pointés']
|
492
|
for column in analyses[key]:
|
493
|
row.append(column.pointe)
|
494
|
rows.append(row)
|
495
|
row = ['Absences']
|
496
|
for column in analyses[key]:
|
497
|
row.append(column.absent)
|
498
|
rows.append(row)
|
499
|
row = ['% absences / pointés']
|
500
|
for column in analyses[key]:
|
501
|
row.append(column.percent_abs)
|
502
|
rows.append(row)
|
503
|
row = ['Excusées']
|
504
|
for column in analyses[key]:
|
505
|
row.append(column.abs_exc)
|
506
|
rows.append(row)
|
507
|
row = ['Non excusées']
|
508
|
for column in analyses[key]:
|
509
|
row.append(column.abs_non_exc)
|
510
|
rows.append(row)
|
511
|
row = ["De l'intervenant"]
|
512
|
for column in analyses[key]:
|
513
|
row.append(column.abs_inter)
|
514
|
rows.append(row)
|
515
|
row = ["Annulés par nous"]
|
516
|
for column in analyses[key]:
|
517
|
row.append(column.annul_nous)
|
518
|
rows.append(row)
|
519
|
row = ['Annulés par la famille']
|
520
|
for column in analyses[key]:
|
521
|
row.append(column.annul_famille)
|
522
|
rows.append(row)
|
523
|
row = ['ESS PPS']
|
524
|
for column in analyses[key]:
|
525
|
row.append(column.abs_ess_pps)
|
526
|
rows.append(row)
|
527
|
row = ['Hospitalisations']
|
528
|
for column in analyses[key]:
|
529
|
row.append(column.enf_hosp)
|
530
|
rows.append(row)
|
531
|
table_2.append(rows)
|
532
|
data_tables.append(table_2)
|
533
|
|
534
|
if statistic.in_service.name == 'CMPP':
|
535
|
table_3 = []
|
536
|
table_3_label = label + ' - non fact.'
|
537
|
table_3.append([table_3_label] + ANNUAL_ACTIVITY_COLUMN_LABELS)
|
538
|
rows = []
|
539
|
row = ['Pointés']
|
540
|
for column in analyses[key]:
|
541
|
row.append(column.pointe)
|
542
|
rows.append(row)
|
543
|
row = ['Présents']
|
544
|
for column in analyses[key]:
|
545
|
row.append(column.acts_present)
|
546
|
rows.append(row)
|
547
|
row = ['De type non fact.']
|
548
|
for column in analyses[key]:
|
549
|
row.append(column.non_facturables)
|
550
|
rows.append(row)
|
551
|
row = ['De type fact.']
|
552
|
for column in analyses[key]:
|
553
|
row.append(column.facturables)
|
554
|
rows.append(row)
|
555
|
row = ['Perdus']
|
556
|
for column in analyses[key]:
|
557
|
row.append(column.perdus)
|
558
|
rows.append(row)
|
559
|
row = ['En doubles']
|
560
|
for column in analyses[key]:
|
561
|
row.append(column.doubles)
|
562
|
rows.append(row)
|
563
|
row = ['Non facturables']
|
564
|
for column in analyses[key]:
|
565
|
row.append(column.nf)
|
566
|
rows.append(row)
|
567
|
row = ['% NF / pointés']
|
568
|
for column in analyses[key]:
|
569
|
row.append(column.percent_nf)
|
570
|
rows.append(row)
|
571
|
table_3.append(rows)
|
572
|
data_tables.append(table_3)
|
573
|
|
574
|
def run_annual_activity(statistic, start_day, analyses, key, label, data_tables, participant=None):
|
575
|
analyses[key] = list()
|
576
|
trim_cnt = 0
|
577
|
for i in range(0, 12):
|
578
|
annual_activity_month_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant)
|
579
|
if not (i + 1) % 3:
|
580
|
trim_cnt += 1
|
581
|
annual_activity_trimester_analysis(statistic, start_day, analyses, key, i, trim_cnt, participant)
|
582
|
end_day = datetime(start_day.year+1, 1, 1)
|
583
|
annual_activity_synthesis_analysis(statistic, start_day, end_day, analyses, key, participant)
|
584
|
annual_activity_build_tables(statistic, analyses, key, label, data_tables)
|
585
|
|
586
|
def annual_activity(statistic):
|
587
|
if not statistic.in_service:
|
588
|
return None
|
589
|
start_day = datetime(datetime.today().year, 1, 1)
|
590
|
if statistic.in_year:
|
591
|
start_day = datetime(statistic.in_year, 1, 1)
|
592
|
data_tables = list()
|
593
|
analyses = dict()
|
594
|
if not statistic.in_participants:
|
595
|
run_annual_activity(statistic, start_day, analyses, 'global', 'Tous', data_tables, participant=None)
|
596
|
else:
|
597
|
for participant in statistic.in_participants:
|
598
|
run_annual_activity(statistic, start_day, analyses, participant.id, str(participant), data_tables, participant=participant)
|
599
|
return [data_tables]
|
600
|
|
601
|
def patients_per_worker_for_period(statistic):
|
602
|
if not statistic.in_service:
|
603
|
return None
|
604
|
data_tables = []
|
605
|
data = []
|
606
|
data.append(['Intervenants', 'Nombre', 'Patients'])
|
607
|
values = []
|
608
|
if not statistic.in_end_date:
|
609
|
statistic.in_end_date = datetime.today()
|
610
|
if not statistic.in_start_date:
|
611
|
statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
|
612
|
acts = None
|
613
|
if statistic.in_patients:
|
614
|
acts = Act.objects.filter(date__gte=statistic.in_start_date,
|
615
|
date__lte=statistic.in_end_date,
|
616
|
patient__service=statistic.in_service,
|
617
|
patient__in=statistic.in_patients)
|
618
|
else:
|
619
|
acts = Act.objects.filter(date__gte=statistic.in_start_date,
|
620
|
date__lte=statistic.in_end_date,
|
621
|
patient__service=statistic.in_service)
|
622
|
analyse = dict()
|
623
|
for act in acts:
|
624
|
for intervene in act.doctors.all():
|
625
|
if statistic.in_participants:
|
626
|
if intervene in statistic.in_participants:
|
627
|
analyse.setdefault(intervene, []).append(str(act.patient))
|
628
|
else:
|
629
|
analyse.setdefault(intervene, []).append(str(act.patient))
|
630
|
o_analyse = OrderedDict(sorted(analyse.items(), key=lambda t: t[0]))
|
631
|
for intervene, patients in o_analyse.iteritems():
|
632
|
lst = list(set(patients))
|
633
|
values.append([str(intervene), len(lst), lst])
|
634
|
data.append(values)
|
635
|
data_tables.append(data)
|
636
|
return [data_tables]
|
637
|
|
638
|
def active_patients_by_state_only(statistic):
|
639
|
if not statistic.in_service:
|
640
|
return None
|
641
|
if not statistic.in_start_date:
|
642
|
statistic.in_start_date = datetime.today()
|
643
|
active_states = None
|
644
|
if statistic.in_service.name == 'CMPP':
|
645
|
active_states = ('TRAITEMENT', 'DIAGNOSTIC')
|
646
|
elif statistic.in_service.name == 'CAMSP':
|
647
|
active_states = ('SUIVI', )
|
648
|
else:
|
649
|
active_states = ('TRAITEMENT', )
|
650
|
patients = [(p.last_name, p.first_name, p.paper_id) \
|
651
|
for p in PatientRecord.objects.filter(service=statistic.in_service) \
|
652
|
if p.get_state_at_day(
|
653
|
statistic.in_start_date).status.type in active_states]
|
654
|
data_tables_set=[[[['En date du :', formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"), len(patients)]]]]
|
655
|
data = []
|
656
|
data.append(['Nom', 'Prénom', 'N° Dossier'])
|
657
|
p_list = []
|
658
|
for ln, fn, pid in patients:
|
659
|
ln = ln or ''
|
660
|
if len(ln) > 1:
|
661
|
ln = ln[0].upper() + ln[1:].lower()
|
662
|
fn = fn or ''
|
663
|
if len(fn) > 1:
|
664
|
fn = fn[0].upper() + fn[1:].lower()
|
665
|
p_list.append((ln, fn, str(pid or '')))
|
666
|
data.append(sorted(p_list,
|
667
|
key=lambda k: k[0]+k[1]))
|
668
|
data_tables_set[0].append(data)
|
669
|
return data_tables_set
|
670
|
|
671
|
def active_patients_with_act(statistic):
|
672
|
def process(patients_list, title):
|
673
|
data_tables = []
|
674
|
data = []
|
675
|
data.append([title, len(patients_list), '', ''])
|
676
|
data_tables.append(data)
|
677
|
data = []
|
678
|
data.append(['Nom', 'Prénom', 'N° Dossier'])
|
679
|
patients_values = patients_list.\
|
680
|
values_list('last_name', 'first_name', 'paper_id')
|
681
|
p_list = []
|
682
|
for ln, fn, pid in patients_values:
|
683
|
ln = ln or ''
|
684
|
if len(ln) > 1:
|
685
|
ln = ln[0].upper() + ln[1:].lower()
|
686
|
fn = fn or ''
|
687
|
if len(fn) > 1:
|
688
|
fn = fn[0].upper() + fn[1:].lower()
|
689
|
p_list.append((ln, fn, str(pid or '')))
|
690
|
data.append(sorted(p_list,
|
691
|
key=lambda k: k[0]+k[1]))
|
692
|
data_tables.append(data)
|
693
|
return data_tables
|
694
|
if not statistic.in_service:
|
695
|
return None
|
696
|
if not statistic.in_end_date:
|
697
|
statistic.in_end_date = datetime.today()
|
698
|
if not statistic.in_start_date:
|
699
|
statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
|
700
|
active_states = None
|
701
|
if statistic.in_service.name == 'CMPP':
|
702
|
active_states = ('TRAITEMENT', 'DIAGNOSTIC')
|
703
|
elif statistic.in_service.name == 'CAMSP':
|
704
|
active_states = ('SUIVI', )
|
705
|
else:
|
706
|
active_states = ('TRAITEMENT', )
|
707
|
|
708
|
data_tables_set = []
|
709
|
data_tables = []
|
710
|
data = []
|
711
|
data.append(['Période', 'Jours'])
|
712
|
data.append([("%s - %s"
|
713
|
% (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
|
714
|
formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
|
715
|
(statistic.in_end_date-statistic.in_start_date).days+1)])
|
716
|
data_tables.append(data)
|
717
|
data_tables_set.append(data_tables)
|
718
|
|
719
|
acts_base = Act.objects.filter(
|
720
|
date__gte=statistic.in_start_date,
|
721
|
date__lte=statistic.in_end_date,
|
722
|
patient__service=statistic.in_service)
|
723
|
acts_valide = acts_base.filter(valide=True)
|
724
|
acts_valide_patients_ids = acts_valide.order_by('patient').\
|
725
|
distinct('patient').values_list('patient')
|
726
|
acts_valide_patients = PatientRecord.objects.filter(
|
727
|
id__in=[patient[0] for patient in acts_valide_patients_ids])
|
728
|
all_patients_ids = acts_base.order_by('patient').distinct('patient').\
|
729
|
values_list('patient')
|
730
|
acts_not_valide_patients = PatientRecord.objects.filter(
|
731
|
id__in=[patient[0] for patient in all_patients_ids
|
732
|
if not patient in acts_valide_patients_ids])
|
733
|
|
734
|
|
735
|
patients_1 = acts_valide_patients.filter(
|
736
|
last_state__status__type__in=active_states)
|
737
|
patients_2 = acts_valide_patients.exclude(
|
738
|
last_state__status__type__in=active_states)
|
739
|
patients_3 = acts_not_valide_patients.filter(
|
740
|
last_state__status__type__in=active_states)
|
741
|
patients_4 = acts_not_valide_patients.exclude(
|
742
|
last_state__status__type__in=active_states)
|
743
|
|
744
|
data_tables_set.append(process(patients_1, 'Patients avec un acte validé et dans un état actif'))
|
745
|
data_tables_set.append(process(patients_2, 'Patients avec un acte validé et dans un état non actif'))
|
746
|
data_tables_set.append(process(patients_3, 'Patients sans acte validé et dans un état actif'))
|
747
|
data_tables_set.append(process(patients_4, 'Patients sans acte validé et dans un état non actif'))
|
748
|
|
749
|
return data_tables_set
|
750
|
|
751
|
def closed_files(statistic):
|
752
|
if not statistic.in_service:
|
753
|
return None
|
754
|
data_tables = []
|
755
|
data1 = []
|
756
|
data1.append(['Période', 'Jours',
|
757
|
'Nombre de dossiers clos durant la période', 'PEC totale', 'PEC moyenne', "Dossiers qui ne sont plus clos"])
|
758
|
data2 = []
|
759
|
data2.append(['Nom', 'Prénom', 'N° Dossier', 'Date de clôture', 'Durée de la PEC', "N'est plus clos"])
|
760
|
if not statistic.in_end_date:
|
761
|
statistic.in_end_date = datetime.today()
|
762
|
if not statistic.in_start_date:
|
763
|
statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
|
764
|
closed_records = FileState.objects.filter(status__type='CLOS',
|
765
|
date_selected__gte=statistic.in_start_date,
|
766
|
date_selected__lte=statistic.in_end_date). \
|
767
|
order_by('patient').distinct('patient').\
|
768
|
values_list('patient')
|
769
|
closed_records = PatientRecord.objects.filter(service=statistic.in_service, id__in=[patient[0]
|
770
|
for patient in closed_records])
|
771
|
total_pec = 0
|
772
|
p_list = []
|
773
|
not_closed_now = 0
|
774
|
for record in closed_records:
|
775
|
ln = record.last_name or ''
|
776
|
if len(ln) > 1:
|
777
|
ln = ln[0].upper() + ln[1:].lower()
|
778
|
fn = record.first_name or ''
|
779
|
if len(fn) > 1:
|
780
|
fn = fn[0].upper() + fn[1:].lower()
|
781
|
current_state = ''
|
782
|
close_date = record.last_state.date_selected.date()
|
783
|
if record.get_current_state().status.type != 'CLOS':
|
784
|
not_closed_now += 1
|
785
|
current_state = record.get_current_state().status.name + \
|
786
|
' le ' + formats.date_format(record.get_current_state(). \
|
787
|
date_selected, "SHORT_DATE_FORMAT")
|
788
|
close_date = FileState.objects.filter(status__type='CLOS',
|
789
|
patient=record).order_by('-date_selected')[0].date_selected.date()
|
790
|
p_list.append((ln, fn, str(record.paper_id or ''),
|
791
|
close_date,
|
792
|
record.care_duration_since_last_contact_or_first_act,
|
793
|
current_state))
|
794
|
total_pec += record.care_duration_since_last_contact_or_first_act
|
795
|
data2.append(sorted(p_list,
|
796
|
key=lambda k: k[0]+k[1]))
|
797
|
avg_pec = 0
|
798
|
if closed_records.count() and total_pec:
|
799
|
avg_pec = total_pec/closed_records.count()
|
800
|
data1.append([("%s - %s"
|
801
|
% (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
|
802
|
formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
|
803
|
(statistic.in_end_date-statistic.in_start_date).days+1,
|
804
|
closed_records.count(), total_pec, avg_pec, not_closed_now)])
|
805
|
data_tables.append(data1)
|
806
|
data_tables.append(data2)
|
807
|
return [data_tables]
|
808
|
|
809
|
def patients_details(statistic):
|
810
|
if not statistic.in_service:
|
811
|
return None
|
812
|
data_tables_set = []
|
813
|
if not statistic.in_end_date:
|
814
|
statistic.in_end_date = datetime.today()
|
815
|
if not statistic.in_start_date:
|
816
|
statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
|
817
|
acts = None
|
818
|
if statistic.in_patients:
|
819
|
acts = Act.objects.filter(date__gte=statistic.in_start_date,
|
820
|
date__lte=statistic.in_end_date,
|
821
|
patient__service=statistic.in_service,
|
822
|
patient__in=statistic.in_patients)
|
823
|
else:
|
824
|
acts = Act.objects.filter(date__gte=statistic.in_start_date,
|
825
|
date__lte=statistic.in_end_date,
|
826
|
patient__service=statistic.in_service)
|
827
|
analyse = dict()
|
828
|
for act in acts:
|
829
|
analyse.setdefault(act.patient, []).append(act)
|
830
|
o_analyse = OrderedDict(sorted(analyse.items(),
|
831
|
key=lambda t: t[0].last_name))
|
832
|
data = []
|
833
|
data.append(['Période', 'Jours',
|
834
|
'Nombre de dossiers'])
|
835
|
data.append([("%s - %s"
|
836
|
% (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
|
837
|
formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
|
838
|
(statistic.in_end_date-statistic.in_start_date).days+1,
|
839
|
len(o_analyse))])
|
840
|
data_tables_set.append([data])
|
841
|
for patient, acts in o_analyse.iteritems():
|
842
|
data_tables = list()
|
843
|
data_tables.append([["%s %s" % (str(patient), str(patient.paper_id))]])
|
844
|
data = []
|
845
|
data.append(["Statut de l'acte", 'Nombre'])
|
846
|
values = []
|
847
|
values.append(('Proposés', len(acts)))
|
848
|
np, absent = 0, 0
|
849
|
act_types = dict()
|
850
|
for a in acts:
|
851
|
if a.is_new():
|
852
|
np += 1
|
853
|
elif a.is_absent():
|
854
|
absent += 1
|
855
|
act_types.setdefault(a.act_type, []).append(a)
|
856
|
values.append(('Non pointés', np))
|
857
|
values.append(('Présents', len(acts) - np - absent))
|
858
|
values.append(('Absents', absent))
|
859
|
data.append(values)
|
860
|
data_tables.append(data)
|
861
|
data = []
|
862
|
data.append(["Types d'acte", "Nombre d'actes proposés"])
|
863
|
values = []
|
864
|
for act_type, acts in act_types.iteritems():
|
865
|
values.append((act_type, len(acts)))
|
866
|
data.append(values)
|
867
|
data_tables.append(data)
|
868
|
|
869
|
data = []
|
870
|
data.append(["Historique", "Nombre de jours par état"])
|
871
|
values = []
|
872
|
for state, duration in patient.get_states_history_with_duration():
|
873
|
values.append(("%s (%s)" % (state.status.name,
|
874
|
formats.date_format(state.date_selected,
|
875
|
"SHORT_DATE_FORMAT")), duration.days))
|
876
|
data.append(values)
|
877
|
data_tables.append(data)
|
878
|
|
879
|
contacts = FileState.objects.filter(patient=patient, status__type='ACCUEIL').order_by('date_selected')
|
880
|
recontact = 'Non'
|
881
|
last_contact = None
|
882
|
first_acts_after_contact = None
|
883
|
if len(contacts) == 1:
|
884
|
last_contact = contacts[0]
|
885
|
elif len(contacts) > 1:
|
886
|
recontact = 'Oui'
|
887
|
last_contact = contacts[len(contacts)-1]
|
888
|
if last_contact:
|
889
|
# inscription act
|
890
|
first_acts_after_contact = Act.objects.filter(patient=patient, date__gte=last_contact.date_selected).order_by('date')
|
891
|
if first_acts_after_contact:
|
892
|
first_act_after_contact = first_acts_after_contact[0]
|
893
|
if first_act_after_contact.date <= statistic.in_end_date.date() and first_act_after_contact.date >= statistic.in_start_date.date():
|
894
|
# inscription during the selected date range.
|
895
|
waiting_duration = first_act_after_contact.date - last_contact.date_selected.date()
|
896
|
data = []
|
897
|
data.append(["Date inscription", "Date accueil", 'Attente', 'Réinscription'])
|
898
|
values = []
|
899
|
values.append((first_act_after_contact.date, last_contact.date_selected.date(), waiting_duration.days, recontact))
|
900
|
data.append(values)
|
901
|
data_tables.append(data)
|
902
|
|
903
|
closed_during_range_date = None
|
904
|
try:
|
905
|
closed_during_range_date = FileState.objects.filter(patient=patient, status__type='CLOS',
|
906
|
date_selected__gte=statistic.in_start_date,
|
907
|
date_selected__lte=statistic.in_end_date).latest('date_selected')
|
908
|
except:
|
909
|
pass
|
910
|
care_duration = patient.care_duration_since_last_contact_or_first_act
|
911
|
closure_date = ''
|
912
|
if closed_during_range_date:
|
913
|
closure_date = closed_during_range_date.date_selected.date
|
914
|
reopen = ''
|
915
|
if closed_during_range_date and not patient.exit_date:
|
916
|
reopen = 'Oui'
|
917
|
data = []
|
918
|
data.append(["Durée de la prise en charge", "Clos pendant la période", "Actes suivants la clôture"])
|
919
|
values = []
|
920
|
values.append((patient.care_duration_since_last_contact_or_first_act, closure_date, reopen))
|
921
|
data.append(values)
|
922
|
data_tables.append(data)
|
923
|
|
924
|
if patient.mdph_requests.exists():
|
925
|
data = []
|
926
|
data.append(["Demande(s) MDPH pendant la période", "Date de la demande", "Demande antérieure à la date de début saisie"])
|
927
|
values = []
|
928
|
for request in patient.mdph_requests.order_by('start_date'):
|
929
|
before = 'Non'
|
930
|
if request.start_date < statistic.in_start_date.date():
|
931
|
before = 'Oui'
|
932
|
values.append(('MDPH : ' + request.mdph.department, request.start_date, before))
|
933
|
data.append(values)
|
934
|
data_tables.append(data)
|
935
|
if patient.mdph_responses.exists():
|
936
|
data = []
|
937
|
data.append(["Réponse(s) MDPH pendant la période", "Date de début", "Date de fin"])
|
938
|
values = []
|
939
|
for response in patient.mdph_responses.order_by('start_date'):
|
940
|
values.append(('MDPH : ' + response.mdph.department, response.start_date, response.end_date))
|
941
|
data.append(values)
|
942
|
data_tables.append(data)
|
943
|
data_tables_set.append(data_tables)
|
944
|
|
945
|
return data_tables_set
|
946
|
|
947
|
def patients_synthesis(statistic):
|
948
|
if not statistic.in_service:
|
949
|
return None
|
950
|
data_tables = []
|
951
|
data = []
|
952
|
data.append(['Période', 'Jours',
|
953
|
'Nombre de dossiers avec un acte validé sur la période',
|
954
|
"Nombre d'actes validés sur la période"])
|
955
|
if not statistic.in_end_date:
|
956
|
statistic.in_end_date = datetime.today()
|
957
|
if not statistic.in_start_date:
|
958
|
statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
|
959
|
acts = Act.objects.filter(valide=True,
|
960
|
date__gte=statistic.in_start_date,
|
961
|
date__lte=statistic.in_end_date,
|
962
|
patient__service=statistic.in_service)
|
963
|
patients = acts.order_by('patient').distinct('patient').\
|
964
|
values_list('patient')
|
965
|
patients = PatientRecord.objects.filter(id__in=[patient[0]
|
966
|
for patient in patients])
|
967
|
nb_patients = patients.count()
|
968
|
data.append([("%s - %s"
|
969
|
% (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
|
970
|
formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
|
971
|
(statistic.in_end_date-statistic.in_start_date).days+1,
|
972
|
nb_patients, acts.count())])
|
973
|
data_tables.append(data)
|
974
|
data = []
|
975
|
data.append(['Féminin', 'Masculin'])
|
976
|
data.append([(patients.filter(gender='2').count(),
|
977
|
patients.filter(gender='1').count())])
|
978
|
data_tables.append(data)
|
979
|
data = []
|
980
|
data.append(['Durée totale de la PEC',
|
981
|
'Durée moyenne de la PEC par patient'])
|
982
|
pec_total = sum([p.care_duration_since_last_contact_or_first_act for p in patients])
|
983
|
data.append([(pec_total, pec_total/nb_patients)])
|
984
|
data_tables.append(data)
|
985
|
data = []
|
986
|
data.append(["Etat du dossier à ce jour", 'Nombre de patients'])
|
987
|
states = dict()
|
988
|
for patient in patients:
|
989
|
states.setdefault(patient.get_current_state().status, []).append(patient)
|
990
|
values = []
|
991
|
closed_patients_tmp = None
|
992
|
for state, ps in states.iteritems():
|
993
|
values.append((state.name, len(ps)))
|
994
|
if state.id == 5:
|
995
|
closed_patients_tmp = ps
|
996
|
data.append(values)
|
997
|
data_tables.append(data)
|
998
|
|
999
|
# Pour les patients inscrits pendant la périodes
|
1000
|
inscriptions = 0
|
1001
|
recontact_cnt = 0
|
1002
|
waiting_duration = timedelta()
|
1003
|
|
1004
|
for patient in patients:
|
1005
|
recontact = False
|
1006
|
contacts = FileState.objects.filter(patient=patient, status__type='ACCUEIL').order_by('date_selected')
|
1007
|
last_contact = None
|
1008
|
first_acts_after_contact = None
|
1009
|
if len(contacts) == 1:
|
1010
|
last_contact = contacts[0]
|
1011
|
elif len(contacts) > 1:
|
1012
|
recontact = True
|
1013
|
last_contact = contacts[len(contacts)-1]
|
1014
|
if last_contact:
|
1015
|
# inscription act
|
1016
|
first_acts_after_contact = Act.objects.filter(patient=patient, date__gte=last_contact.date_selected).order_by('date')
|
1017
|
if first_acts_after_contact:
|
1018
|
first_act_after_contact = first_acts_after_contact[0]
|
1019
|
if first_act_after_contact.date <= statistic.in_end_date.date() and first_act_after_contact.date >= statistic.in_start_date.date():
|
1020
|
# inscription during the selected date range.
|
1021
|
waiting_duration += first_act_after_contact.date - last_contact.date_selected.date()
|
1022
|
inscriptions += 1
|
1023
|
if recontact:
|
1024
|
recontact_cnt += 1
|
1025
|
if inscriptions:
|
1026
|
data = []
|
1027
|
data.append(['Inscriptions (premier acte suivant le dernier contact dans la période)', 'Dont réinscription', "Durée moyenne de l'attente"])
|
1028
|
data.append([(inscriptions, recontact_cnt, (waiting_duration/inscriptions).days)])
|
1029
|
data_tables.append(data)
|
1030
|
|
1031
|
closed_records = FileState.objects.filter(status__type='CLOS',
|
1032
|
date_selected__gte=statistic.in_start_date,
|
1033
|
date_selected__lte=statistic.in_end_date, patient__in=patients). \
|
1034
|
order_by('patient').distinct('patient').\
|
1035
|
values_list('patient')
|
1036
|
closed_records = PatientRecord.objects.filter(service=statistic.in_service, id__in=[patient[0]
|
1037
|
for patient in closed_records])
|
1038
|
total_pec = 0
|
1039
|
not_closed_now = 0
|
1040
|
for record in closed_records:
|
1041
|
if record.get_current_state().status.type != 'CLOS':
|
1042
|
not_closed_now += 1
|
1043
|
total_pec += record.care_duration_since_last_contact_or_first_act
|
1044
|
avg_pec = 0
|
1045
|
if closed_records.count() and total_pec:
|
1046
|
avg_pec = total_pec/closed_records.count()
|
1047
|
if closed_records.count():
|
1048
|
data = []
|
1049
|
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"])
|
1050
|
data.append([(closed_records.count(), total_pec, avg_pec, not_closed_now)])
|
1051
|
data_tables.append(data)
|
1052
|
|
1053
|
mdph_requests = 0
|
1054
|
mdph_requests_before = 0
|
1055
|
for patient in patients:
|
1056
|
if patient.mdph_requests.exists():
|
1057
|
mdph_requests += 1
|
1058
|
# We only look to the last one
|
1059
|
if patient.mdph_requests.order_by('-start_date')[0].start_date < statistic.in_start_date.date():
|
1060
|
mdph_requests_before +=1
|
1061
|
data = []
|
1062
|
data.append(['Dossier avec une demande MDPH', "Dont la dernière demande a été faite avant la période"])
|
1063
|
data.append([(mdph_requests, mdph_requests_before)])
|
1064
|
data_tables.append(data)
|
1065
|
|
1066
|
birth_years = dict()
|
1067
|
patients_without_birthyear = []
|
1068
|
for patient in patients:
|
1069
|
try:
|
1070
|
birth_years.setdefault(patient.birthdate.year, []).append(patient)
|
1071
|
except:
|
1072
|
patients_without_birthyear.append(patient)
|
1073
|
data = []
|
1074
|
data.append(['Année de naissance', "Nombre de dossiers"])
|
1075
|
values = []
|
1076
|
for birth_year, pts in birth_years.iteritems():
|
1077
|
values.append((birth_year, len(pts)))
|
1078
|
if patients_without_birthyear:
|
1079
|
values.append(('%d patient(s) sans date de naissance' % len(patients_without_birthyear), patients_without_birthyear))
|
1080
|
data.append(values)
|
1081
|
data_tables.append(data)
|
1082
|
|
1083
|
lower_bounds = [0, 3, 5, 7, 11, 16, 20, 25, 30, 35, 40, 45, 50, 55, 60, 75, 85, 96]
|
1084
|
anap_code = 198
|
1085
|
data = []
|
1086
|
data.append(["Code ANAP", "Tranche d'âge (au %s)" \
|
1087
|
% formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT"),
|
1088
|
"Nombre de dossiers"])
|
1089
|
values = []
|
1090
|
for i in range(len(lower_bounds)):
|
1091
|
lower_bound = lower_bounds[i]
|
1092
|
if i == len(lower_bounds) - 1:
|
1093
|
values.append([anap_code, "De %d ans et plus" % lower_bound, 0])
|
1094
|
else:
|
1095
|
values.append([anap_code, "De %d à %d ans" % (lower_bound, lower_bounds[i + 1] - 1), 0])
|
1096
|
anap_code += 1
|
1097
|
for patient in patients:
|
1098
|
try:
|
1099
|
age = statistic.in_end_date.date() - patient.birthdate
|
1100
|
age = age.days / 365
|
1101
|
i = 0
|
1102
|
while age >= lower_bounds[i+1]:
|
1103
|
i += 1
|
1104
|
if i == len(lower_bounds) - 1:
|
1105
|
break
|
1106
|
values[i][2] += 1
|
1107
|
except:
|
1108
|
pass
|
1109
|
data.append(values)
|
1110
|
data_tables.append(data)
|
1111
|
|
1112
|
jobs = dict()
|
1113
|
for patient in patients:
|
1114
|
if patient.job_mother:
|
1115
|
jobs.setdefault(patient.job_mother, []).append(patient)
|
1116
|
if patient.job_father:
|
1117
|
jobs.setdefault(patient.job_father, []).append(patient)
|
1118
|
data = []
|
1119
|
data.append(["Profession d'un parent", "Nombre de dossiers"])
|
1120
|
values = []
|
1121
|
for job, pts in jobs.iteritems():
|
1122
|
values.append((job, len(pts)))
|
1123
|
data.append(values)
|
1124
|
data_tables.append(data)
|
1125
|
|
1126
|
provenances = dict()
|
1127
|
unknown = 0
|
1128
|
for patient in patients:
|
1129
|
if patient.provenance:
|
1130
|
provenances.setdefault(patient.provenance, []).append(patient)
|
1131
|
else:
|
1132
|
unknown += 1
|
1133
|
data = []
|
1134
|
data.append(["Provenances", "Nombre de dossiers"])
|
1135
|
values = []
|
1136
|
for provenance, pts in provenances.iteritems():
|
1137
|
values.append((provenance, len(pts)))
|
1138
|
values.append(('Non renseignée', unknown))
|
1139
|
data.append(values)
|
1140
|
data_tables.append(data)
|
1141
|
|
1142
|
outmotives = dict()
|
1143
|
for patient in patients:
|
1144
|
if patient.outmotive:
|
1145
|
outmotives.setdefault(patient.outmotive, []).append(patient)
|
1146
|
data = []
|
1147
|
data.append(["Motifs de sortie", "Nombre de dossiers"])
|
1148
|
values = []
|
1149
|
for outmotive, pts in outmotives.iteritems():
|
1150
|
values.append((outmotive, len(pts)))
|
1151
|
data.append(values)
|
1152
|
data_tables.append(data)
|
1153
|
|
1154
|
outtos = dict()
|
1155
|
for patient in patients:
|
1156
|
if patient.outto:
|
1157
|
outtos.setdefault(patient.outto, []).append(patient)
|
1158
|
data = []
|
1159
|
data.append(["Orientations", "Nombre de dossiers"])
|
1160
|
values = []
|
1161
|
for outto, pts in outtos.iteritems():
|
1162
|
values.append((outto, len(pts)))
|
1163
|
data.append(values)
|
1164
|
data_tables.append(data)
|
1165
|
|
1166
|
return [data_tables]
|
1167
|
|
1168
|
def acts_synthesis(statistic):
|
1169
|
if not statistic.in_service:
|
1170
|
return None
|
1171
|
if not statistic.in_end_date:
|
1172
|
statistic.in_end_date = datetime.today()
|
1173
|
if not statistic.in_start_date:
|
1174
|
statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
|
1175
|
data_tables = []
|
1176
|
data = []
|
1177
|
data.append(['Période', 'Jours',
|
1178
|
"Nombre d'actes proposés sur la période",
|
1179
|
"Nombre d'actes validés sur la période"])
|
1180
|
acts = Act.objects.filter(date__gte=statistic.in_start_date,
|
1181
|
date__lte=statistic.in_end_date,
|
1182
|
patient__service=statistic.in_service)
|
1183
|
acts_valide = acts.filter(valide=True)
|
1184
|
data.append([("%s - %s"
|
1185
|
% (formats.date_format(statistic.in_start_date, "SHORT_DATE_FORMAT"),
|
1186
|
formats.date_format(statistic.in_end_date, "SHORT_DATE_FORMAT")),
|
1187
|
(statistic.in_end_date-statistic.in_start_date).days+1,
|
1188
|
acts.count(), acts_valide.count())])
|
1189
|
data_tables.append(data)
|
1190
|
|
1191
|
acts_types = dict()
|
1192
|
for act in acts:
|
1193
|
acts_types.setdefault(act.act_type, []).append(act)
|
1194
|
data = []
|
1195
|
data.append(["Types des actes", "Nombre d'actes"])
|
1196
|
values = []
|
1197
|
for act_type, acts in acts_types.iteritems():
|
1198
|
values.append((act_type, len(acts)))
|
1199
|
data.append(values)
|
1200
|
data_tables.append(data)
|
1201
|
|
1202
|
for act_type, acts in acts_types.iteritems():
|
1203
|
analysis = {'Non pointés': 0,
|
1204
|
'Reportés': 0, 'Absents': 0, 'Présents': 0}
|
1205
|
for a in acts:
|
1206
|
if a.is_new():
|
1207
|
analysis['Non pointés'] += 1
|
1208
|
elif a.is_absent():
|
1209
|
state = a.get_state()
|
1210
|
if state.state_name == 'REPORTE':
|
1211
|
analysis['Reportés'] += 1
|
1212
|
else:
|
1213
|
analysis['Absents'] += 1
|
1214
|
else:
|
1215
|
analysis['Présents'] += 1
|
1216
|
data = []
|
1217
|
data.append(["Type d'acte", act_type])
|
1218
|
values = []
|
1219
|
for status, number in analysis.iteritems():
|
1220
|
values.append((status, number))
|
1221
|
data.append(values)
|
1222
|
data_tables.append(data)
|
1223
|
|
1224
|
acts_count_participants = dict()
|
1225
|
for act in acts_valide:
|
1226
|
acts_count_participants.setdefault(act.doctors.count(), []).append(act)
|
1227
|
data = []
|
1228
|
data.append(["Nombre d'intervenants des actes réalisés", "Nombre d'actes", "Nombre de dossiers concernés"])
|
1229
|
values = []
|
1230
|
for number, acts_counted in acts_count_participants.iteritems():
|
1231
|
values.append((number, len(acts_counted), len(set([a.patient.id for a in acts_counted]))))
|
1232
|
data.append(values)
|
1233
|
data_tables.append(data)
|
1234
|
|
1235
|
return [data_tables]
|
1236
|
|
1237
|
def acts_synthesis_cmpp(statistic):
|
1238
|
data_tables_set = []
|
1239
|
if not statistic.in_service:
|
1240
|
return None
|
1241
|
if not statistic.in_end_date:
|
1242
|
statistic.in_end_date = datetime.today()
|
1243
|
if not statistic.in_start_date:
|
1244
|
statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
|
1245
|
acts = Act.objects.filter(date__gte=statistic.in_start_date,
|
1246
|
date__lte=statistic.in_end_date,
|
1247
|
patient__service=statistic.in_service)
|
1248
|
acts_billed = acts.filter(is_billed=True)
|
1249
|
patients_billed = dict()
|
1250
|
for act in acts_billed:
|
1251
|
patients_billed.setdefault(act.patient, [False, False])
|
1252
|
if act.get_hc_tag() and act.get_hc_tag()[0] == 'D':
|
1253
|
patients_billed[act.patient][0] = True
|
1254
|
elif act.get_hc_tag() and act.get_hc_tag()[0] == 'T':
|
1255
|
patients_billed[act.patient][1] = True
|
1256
|
values1, values2, values3 = [], [], []
|
1257
|
for patient, vals in patients_billed.iteritems():
|
1258
|
pfields = [patient.last_name, patient.first_name, patient.paper_id]
|
1259
|
if vals == [True, False]:
|
1260
|
values1.append(pfields)
|
1261
|
elif vals == [False, True]:
|
1262
|
values2.append(pfields)
|
1263
|
elif vals == [True, True]:
|
1264
|
values3.append(pfields)
|
1265
|
cols = ['Nom', 'Prénom', 'Numéro de dossier']
|
1266
|
data_tables_set.append([[['Seulement facturé en diagnostic'], [[len(values1)]]], [cols, sorted(values1, key=lambda t: t[0])]])
|
1267
|
data_tables_set.append([[['Seulement facturé en traitement'], [[len(values2)]]], [cols, sorted(values2, key=lambda t: t[0])]])
|
1268
|
data_tables_set.append([[['Facturé en diagnostic et en traitement'], [[len(values3)]]], [cols, sorted(values3, key=lambda t: t[0])]])
|
1269
|
return data_tables_set
|
1270
|
|
1271
|
def mises(statistic):
|
1272
|
if not statistic.in_service:
|
1273
|
return None
|
1274
|
if not statistic.in_end_date:
|
1275
|
statistic.in_end_date = datetime.today()
|
1276
|
if not statistic.in_start_date:
|
1277
|
statistic.in_start_date = datetime(statistic.in_end_date.year, 1, 1)
|
1278
|
acts = Act.objects.filter(valide='True',
|
1279
|
date__gte=statistic.in_start_date,
|
1280
|
date__lte=statistic.in_end_date,
|
1281
|
patient__service=statistic.in_service)
|
1282
|
patients = acts.order_by('patient').distinct('patient').\
|
1283
|
values_list('patient')
|
1284
|
patients = PatientRecord.objects.filter(id__in=[patient[0]
|
1285
|
for patient in patients])
|
1286
|
pathologies = dict()
|
1287
|
for patient in patients:
|
1288
|
for pathology in patient.mises_1.all():
|
1289
|
pathologies.setdefault(pathology, 0)
|
1290
|
pathologies[pathology] += 1
|
1291
|
for pathology in patient.mises_2.all():
|
1292
|
pathologies.setdefault(pathology, 0)
|
1293
|
pathologies[pathology] += 1
|
1294
|
for pathology in patient.mises_3.all():
|
1295
|
pathologies.setdefault(pathology, 0)
|
1296
|
pathologies[pathology] += 1
|
1297
|
data = [['Pathologies MISES', 'Nombre de patients concernés']]
|
1298
|
data.append(OrderedDict(sorted(pathologies.items(), key=lambda t: t[0].ordering_code)).items())
|
1299
|
return [[data]]
|
1300
|
|
1301
|
|
1302
|
class Statistic(models.Model):
|
1303
|
patients = models.ManyToManyField('dossiers.PatientRecord',
|
1304
|
null=True, blank=True, default=None)
|
1305
|
participants = models.ManyToManyField('personnes.People',
|
1306
|
null=True, blank=True, default=None)
|
1307
|
in_start_date = None
|
1308
|
in_end_date = None
|
1309
|
in_service = None
|
1310
|
in_participants = None
|
1311
|
in_patients = None
|
1312
|
in_year = None
|
1313
|
|
1314
|
def __init__(self, name=None, inputs=dict()):
|
1315
|
self.name = name
|
1316
|
params = STATISTICS.get(name, {})
|
1317
|
self.display_name = params['display_name']
|
1318
|
self.category = params['category']
|
1319
|
self.inputs = inputs
|
1320
|
self.in_participants = list()
|
1321
|
participants = inputs.get('participants')
|
1322
|
if participants:
|
1323
|
p_str_ids = [p for p in participants.split('|') if p]
|
1324
|
for str_id in p_str_ids:
|
1325
|
try:
|
1326
|
self.in_participants.append(Worker.objects.get(pk=int(str_id)))
|
1327
|
except:
|
1328
|
pass
|
1329
|
self.in_patients = list()
|
1330
|
patients = inputs.get('patients')
|
1331
|
if patients:
|
1332
|
p_str_ids = [p for p in patients.split('|') if p]
|
1333
|
for str_id in p_str_ids:
|
1334
|
try:
|
1335
|
self.in_patients.append(PatientRecord.objects.get(pk=int(str_id)))
|
1336
|
except:
|
1337
|
pass
|
1338
|
self.in_service = inputs.get('service')
|
1339
|
self.in_start_date = None
|
1340
|
try:
|
1341
|
self.in_start_date = datetime.strptime(inputs.get('start_date'),
|
1342
|
"%d/%m/%Y")
|
1343
|
except:
|
1344
|
pass
|
1345
|
self.in_end_date = None
|
1346
|
try:
|
1347
|
self.in_end_date = datetime.strptime(inputs.get('end_date'),
|
1348
|
"%d/%m/%Y")
|
1349
|
except:
|
1350
|
pass
|
1351
|
|
1352
|
def get_data(self):
|
1353
|
func = globals()[self.name]
|
1354
|
self.data = func(self)
|
1355
|
return self.data
|
1356
|
|
1357
|
def render_to_csv(self):
|
1358
|
_delimiter = ';'
|
1359
|
_quotechar = '|'
|
1360
|
_doublequote = True
|
1361
|
_skipinitialspace = False
|
1362
|
_lineterminator = '\r\n'
|
1363
|
_quoting = csv.QUOTE_MINIMAL
|
1364
|
if getattr(settings, 'CSVPROFILE', None):
|
1365
|
csv_profile = settings.CSVPROFILE
|
1366
|
_delimiter = csv_profile.get('delimiter', ';')
|
1367
|
_quotechar = csv_profile.get('quotechar', '|')
|
1368
|
_doublequote = csv_profile.get('doublequote', True)
|
1369
|
_skipinitialspace = csv_profile.get('skipinitialspace', False)
|
1370
|
_lineterminator = csv_profile.get('lineterminator', '\r\n')
|
1371
|
_quoting = csv_profile.get('quoting', csv.QUOTE_MINIMAL)
|
1372
|
class CSVProfile(csv.Dialect):
|
1373
|
delimiter = _delimiter
|
1374
|
quotechar = _quotechar
|
1375
|
doublequote = _doublequote
|
1376
|
skipinitialspace = _skipinitialspace
|
1377
|
lineterminator = _lineterminator
|
1378
|
quoting = _quoting
|
1379
|
csv.register_dialect('csv_profile', CSVProfile())
|
1380
|
encoding = getattr(settings, 'CSV_ENCODING', 'utf-8')
|
1381
|
# Python 3: , encoding=encoding
|
1382
|
# with tempfile.NamedTemporaryFile(delete=False) as temp_out_csv:
|
1383
|
# try:
|
1384
|
# writer = csv.writer(temp_out_csv, dialect='csv_profile')
|
1385
|
# for data_set in self.data:
|
1386
|
# for data in data_set:
|
1387
|
# writer.writerow(data[0])
|
1388
|
# if len(data) > 1:
|
1389
|
# for d in data[1]:
|
1390
|
# writer.writerow(d)
|
1391
|
# writer.writerow([])
|
1392
|
# writer.writerow([])
|
1393
|
# return temp_out_csv.name
|
1394
|
# except Exception, e:
|
1395
|
# print e
|
1396
|
# try:
|
1397
|
# os.unlink(temp_out_pdf.name)
|
1398
|
# except:
|
1399
|
# pass
|
1400
|
|
1401
|
import codecs
|
1402
|
filename = None
|
1403
|
with tempfile.NamedTemporaryFile(delete=False) as temp_out_csv:
|
1404
|
filename = temp_out_csv.name
|
1405
|
temp_out_csv.close()
|
1406
|
with codecs.open(filename, 'w+b', encoding=encoding) as encoded_f:
|
1407
|
try:
|
1408
|
writer = csv.writer(encoded_f, dialect='csv_profile')
|
1409
|
for data_set in self.data:
|
1410
|
for data in data_set:
|
1411
|
writer.writerow(data[0])
|
1412
|
if len(data) > 1:
|
1413
|
for d in data[1]:
|
1414
|
writer.writerow(d)
|
1415
|
writer.writerow([])
|
1416
|
writer.writerow([])
|
1417
|
return filename
|
1418
|
except:
|
1419
|
try:
|
1420
|
os.unlink(temp_out_pdf.name)
|
1421
|
except:
|
1422
|
pass
|
1423
|
|
1424
|
def get_file(self):
|
1425
|
self.get_data()
|
1426
|
return self.render_to_csv()
|