Project

General

Profile

« Previous | Next » 

Revision 1c2fd868

Added by Benjamin Dauvergne almost 12 years ago

scripts: add import_rs2.py

View differences:

scripts/import_rs2.py
1
# -*- coding: utf-8 -*-
2
#!/usr/bin/env python
3

  
4
import os
5
import csv
6

  
7
from datetime import datetime, date
8

  
9
import calebasse.settings
10
import django.core.management
11

  
12
django.core.management.setup_environ(calebasse.settings)
13

  
14
from django.db import transaction
15
from calebasse.agenda.models import EventWithAct
16
from calebasse.dossiers.models import PatientRecord
17
from calebasse.personnes.models import Worker
18
from calebasse.ressources.models import Service
19
from calebasse.ressources.models import ActType
20
from calebasse.actes.models import Act, ActValidationState
21

  
22
from import_dossiers import map_cs
23

  
24
# Configuration
25
db_path = "./scripts/20130104-213225"
26

  
27
dbs = ["F_ST_ETIENNE_SESSAD_TED", "F_ST_ETIENNE_CMPP", "F_ST_ETIENNE_CAMSP", "F_ST_ETIENNE_SESSAD"]
28
# dbs = ["F_ST_ETIENNE_SESSAD_TED"]
29

  
30
def _to_datetime(str_date):
31
    if not str_date:
32
        return None
33
    return datetime.strptime(str_date[:19], "%Y-%m-%d %H:%M:%S")
34

  
35
def _to_date(str_date):
36
    dt = _to_datetime(str_date)
37
    return dt and dt.date()
38

  
39
def _to_time(str_date):
40
    dt = _to_datetime(str_date)
41
    return dt and dt.time()
42

  
43
def _to_duration(str_date):
44
    dt = _to_datetime(str_date)
45
    if dt is None:
46
        return None
47
    return dt - datetime(1900, 01, 01, 0, 0)
48

  
49
def _to_int(str_int):
50
    if not str_int:
51
        return None
52
    return int(str_int)
53

  
54
def _get_dict(cols, line):
55
    """"""
56
    res = {}
57
    for i, data in enumerate(line):
58
        res[cols[i]] = data.decode('utf-8')
59
    return res
60

  
61
def batch_delete(qs, limit):
62
    count = qs.count()
63
    i = 0
64
    while i < count:
65
        ids = qs[i:i+limit].values_list('pk', flat=True)
66
        qs.filter(pk__in=ids).delete()
67
        i += limit
68

  
69

  
70
PERIOD_FAURE_NOUS = {1 : 1,
71
2 : 2,
72
3 : 3,
73
4 : 4,
74
5: 6,
75
6: 7,
76
7: 8,
77
8: 9,
78
9: None,
79
10: 10,
80
12: 11,
81
13: 12,
82
}
83

  
84
JOURS = {1: 'lundi',
85
2: 'mardi',
86
3: 'mercredi',
87
4: 'jeudi',
88
5: 'vendredi'
89
}
90

  
91
dic_worker = {}
92

  
93
def load_csv(db, name, offset=0, limit=9999999, id_column=0, year=None):
94
    records = []
95
    idx = {}
96

  
97
    csvfile = open(os.path.join(db_path, db, name + '.csv'), 'rb')
98
    csvlines = csv.reader(csvfile, delimiter=';', quotechar='|')
99
    cols = csvlines.next()
100
    i = 0
101
    for line in csvlines:
102
        if not (offset <= int(line[id_column]) < offset+limit):
103
            continue
104
        data = _get_dict(cols, line)
105
        if year and not (('date_rdv' in data and data['date_rdv'].startswith(str(year))) \
106
                or ('date_debut' in data and data['date_debut'].startswith(str(year)))):
107
            continue
108
        records.append(data)
109
        idx[data['id']] = i
110
        i += 1
111
    csvfile.close()
112
    return records, idx, cols
113

  
114
def add_invalid(d, reason):
115
    d.setdefault('invalid', '')
116
    if d['invalid']:
117
        d['invalid'] += ', '
118
    d['invalid'] += reason
119

  
120
@transaction.commit_on_success
121
def main():
122
    """ """
123

  
124
    workers = Worker.objects.all()
125
    for db in dbs:
126
        workers_idx = {}
127
        act_types_idx = {}
128
        if "F_ST_ETIENNE_CMPP" == db:
129
            service = Service.objects.get(name="CMPP")
130
        elif "F_ST_ETIENNE_CAMSP" == db:
131
            service = Service.objects.get(name="CAMSP")
132
        elif "F_ST_ETIENNE_SESSAD_TED" == db:
133
            service = Service.objects.get(name="SESSAD TED")
134
        elif "F_ST_ETIENNE_SESSAD" == db:
135
            service = Service.objects.get(name="SESSAD DYS")
136

  
137
        print '===', service.name, '==='
138
        print datetime.now()
139

  
140
        for i, worker in enumerate(workers):
141
            if service.name == 'CMPP':
142
                j = worker.old_cmpp_id
143
            elif service.name == 'CAMSP':
144
                j = worker.old_camsp_id
145
            elif service.name == 'SESSAD DYS':
146
                j = worker.old_sessad_dys_id
147
            elif service.name == 'SESSAD TED':
148
                j = worker.old_sessad_ted_id
149
            else:
150
                print "service inconnu!!!"
151
                exit(0)
152
            if j:
153
                workers_idx[j] = worker
154

  
155
        act_types = ActType.objects.for_service(service)
156
        act_type_id_not_found = set()
157
        for i, act_type in enumerate(act_types):
158
            j = act_type.old_id
159
            if j:
160
                act_types_idx[j] = act_type
161
            else:
162
                act_type_id_not_found.add(act_type)
163
        print "%s - Nombre de types d'actes : %d" % (service.name, len(act_types))
164
        print "%s - Liste des types d'actes sans id : %s" % (service.name, str(act_type_id_not_found))
165

  
166
        invalid_rs = set()
167
        invalid_rr = set()
168
        new_rs = []
169
        new_rr = []
170
        invalid_rs_csv = open('./scripts/invalid_rs_%s.csv' % (service.name, ), 'wb+')
171
        invalid_rs_writer = csv.writer(invalid_rs_csv, delimiter=',',
172
                quotechar='"', quoting=csv.QUOTE_MINIMAL)
173
        invalid_rr_csv = open('./scripts/invalid_rr_%s.csv' % (service.name, ), 'wb+')
174
        invalid_rr_writer = csv.writer(invalid_rr_csv, delimiter=',',
175
                quotechar='"', quoting=csv.QUOTE_MINIMAL)
176
        for year in range(2011, 2014):
177
            print service.name, ' - Year', year
178
            rs_data, rs_idx, rs_cols = load_csv(db, 'rs', year=year)
179
            rr_data, rr_idx, rr_cols = load_csv(db, 'rr', year=year)
180
            print service.name, year, 'read', len(rs_data), 'rs and', len(rr_data), 'rr'
181
            rs_cols.extend(['workers', 'invalid'])
182
            rr_cols.extend(['workers', 'invalid'])
183
            invalid_rs_writer.writerow(map(lambda x: x.encode('utf-8'), rs_cols))
184
            invalid_rr_writer.writerow(map(lambda x: x.encode('utf-8'), rr_cols))
185

  
186
            single_rdv_idx = dict(EventWithAct.objects.filter(services=service,
187
                    start_datetime__year=year,
188
                    recurrence_periodicity__isnull=True).values_list('old_rs_id', 'id'))
189
            multi_rdv_idx = dict(EventWithAct.objects.filter(services=service,
190
                    start_datetime__year=year,
191
                    recurrence_periodicity__isnull=False).values_list('old_rr_id', 'id'))
192

  
193
            rs_details_data, _, _ = load_csv(db, 'details_rs')
194
            rr_details_data, _, _ = load_csv(db, 'details_rr')
195

  
196
            def set_act_type(row, not_found=None):
197
                act_type_id = row['type_acte']
198
                if act_type_id == '0':
199
                    add_invalid(row, 'no act_id=>not importable')
200
                elif act_type_id in act_types_idx:
201
                    row['act_type'] = act_types_idx[act_type_id]
202
                else:
203
                    add_invalid(row, 'act_type not found %s' % act_type_id)
204
                    if not_found:
205
                        not_found.add(act_type_id)
206

  
207
            def handle_details(data, idx, details, id_key):
208
                not_found = set()
209
                for detail in details:
210
                    i = detail[id_key]
211
                    thera_id = detail['thera_id']
212
                    if i not in idx:
213
                        continue
214
                    row = data[idx[i]]
215
                    if thera_id in workers_idx:
216
                        workers = row.setdefault('workers', set())
217
                        workers.add(workers_idx[thera_id])
218
                    else:
219
                        # add_invalid(row, 'unknown thera_id %s' % thera_id)
220
                        not_found.add(thera_id)
221
                print "%s - Liste des worker not found : %s" % (service.name, str(set(not_found)))
222

  
223
            print ' - Traitement rs_detail....'
224
            handle_details(rs_data, rs_idx, rs_details_data, 'rs_id')
225
            print ' - Traitement rr_detail....'
226
            handle_details(rr_data, rr_idx, rr_details_data, 'rr_id')
227

  
228
            enfant_idx = {}
229
            for enfant in PatientRecord.objects.filter(service=service):
230
                enfant_idx[enfant.old_id] = enfant
231

  
232
            def set_enfant(row, not_found=None):
233
                # connect enfant
234
                enfant_id = row['enfant_id']
235
                if enfant_id == '0':
236
                    add_invalid(row, 'no enfant_id=>not an appointment')
237
                    row['event'] = True
238
                elif enfant_id in enfant_idx:
239
                    row['enfant'] = enfant_idx[enfant_id]
240
                else:
241
                    add_invalid(row, 'enfant_id not found %s' % enfant_id)
242
                    if not_found:
243
                        not_found.add(enfant_id)
244

  
245
            enfant_not_found = set()
246
            rr_not_found = set()
247
            rs_without_act_type = set()
248
            unknown_act_type_id = set()
249
            for rs in rs_data:
250
                if rs['id'] in single_rdv_idx:
251
                    continue
252
                rs.setdefault('workers', set())
253
                rs['exception'] = False
254
                rs['event'] = False
255
                rs['date'] = _to_date(rs['date_rdv'])
256
                # connect enfant
257
                set_enfant(rs)
258
                set_act_type(rs)
259
                if rs['event']:
260
                    continue
261
                # connect rr
262
                rr_id = rs['rr_ev_id']
263
                if rr_id:
264
                    if rr_id.startswith('ev_'):
265
                        continue
266
                rs['time'] = _to_time(rs['heure'])
267
                rs['duration'] = _to_duration(rs['duree'])
268
                rs['start_datetime'] = datetime.combine(rs['date'], rs['time'])
269
                rs['end_datetime'] = rs['start_datetime'] + rs['duration']
270
                if len(rs['workers']) == 0:
271
                    add_invalid(rs, 'aucun participant')
272
                if rs.get('invalid') and not rs['event']:
273
                    invalid_rs.add(rs['id'])
274
                    invalid_rs_writer.writerow([ unicode(rs[col]).encode('utf-8') for col in rs_cols ])
275
                else:
276
                    new_rs.append(rs)
277

  
278

  
279
            print "%s - Liste des enfants not found : %s" % (service.name, str(enfant_not_found))
280
            print "%s - Liste des RR not found : %s" % (service.name, str(rr_not_found))
281
            print "%s - Liste des RS sans type d'acte : %s" % (service.name, str(rs_without_act_type))
282
            print "%s - Liste des types d'actes inconnus : %s" % (service.name, str(unknown_act_type_id))
283
            print
284

  
285
            enfant_not_found = set()
286
            rr_not_found = set()
287
            rs_without_act_type = set()
288
            unknown_act_type_id = set()
289
            for rr in rr_data:
290
                if rr['id'] in multi_rdv_idx:
291
                    continue
292
                rr['event'] = False
293
                rs.setdefault('workers', set())
294
                rr.setdefault('exceptions', [])
295
                rr['start_date'] = _to_date(rr['date_debut'])
296
                rr['end_date'] = _to_date(rr['date_fin'])
297
                if rr['end_date'] and rr['start_date'] > rr['end_date']:
298
                    add_invalid(rr, 'date_fin < date_debut')
299
                rr['time'] = _to_time(rr['heure'])
300
                rr['duration'] = _to_duration(rr['duree'])
301
                rr['start_datetime'] = datetime.combine(rr['start_date'], rr['time'])
302
                rr['end_datetime'] = rr['start_datetime'] + rr['duration']
303
                # connect rythme
304
                rr['rythme'] = int(rr['rythme'])
305
                if PERIOD_FAURE_NOUS.get(rr['rythme']):
306
                    rr['recurrence_periodicity'] = PERIOD_FAURE_NOUS[rr['rythme']]
307
                else:
308
                    add_invalid(rr, 'rythme not found %s' % rr['rythme'])
309
                set_enfant(rr)
310
                set_act_type(rr)
311
                if rr['event']:
312
                    continue
313
                if len(rr['workers']) == 0:
314
                    add_invalid(rr, 'aucun participant')
315
                if rr.get('invalid'):
316
                    invalid_rr.add(rr['id'])
317
                    invalid_rr_writer.writerow([ unicode(rr[col]).encode('utf-8') for col in rr_cols ])
318
                else:
319
                    new_rr.append(rr)
320
        print service.name, 'found', len(new_rs), 'individual rdv not imported'
321
        print service.name, 'found', len(invalid_rs), 'individual rdv invalid'
322
        print service.name, 'found', len(new_rr), 'multiple rdv not imported'
323
        print service.name, 'found', len(invalid_rr), 'multiple rdv invalid'
324

  
325
        for row in new_rs:
326
            act_id = row['base_id']
327
            if act_id == '0':
328
                continue
329
            acts = Act.objects.filter(old_id=act_id)
330
            row['act'] = None
331
            if len(acts) == 0:
332
                print service.name, 'act not imported', act_id, 'linked to rs', row['id']
333
            elif len(acts) > 1:
334
                print service.name, 'more than one act', acts.values_list('id', flat=True), 'linked to rs', row['id']
335
            else:
336
                row['act'] = acts[0]
337

  
338

  
339
        # RR
340
        for row in new_rr:
341
            event = EventWithAct.objects.create(
342
                    patient=row['enfant'],
343
                    start_datetime=row['start_datetime'],
344
                    end_datetime=row['end_datetime'],
345
                    act_type=row['act_type'],
346
                    old_rr_id=row['id'],
347
                    title=row['enfant'].display_name,
348
                    description=row['texte'],
349
                    recurrence_periodicity=row['recurrence_periodicity'],
350
                    recurrence_end_date=row['end_date'])
351
            event.services = [ service ]
352
            event.participants = row['workers']
353
            print 'created', event
354
        for row in new_rs:
355
            if row['exception'] or row.get('invalid'):
356
                continue
357
            exception_to = None
358
            exception_date = None
359
            if row['rr_ev_id']:
360
                _, rr_id = row['rr_ev_id'].split('_')
361
                e = EventWithAct.objects.filter(old_rr_id=rr_id)
362
                if len(e) == 0:
363
                    pass
364
                elif len(e) > 1:
365
                    add_invalid(row, 'more than one recurring event %s' % e.values_list('id', flat=True))
366
                    invalid_rs_writer.writerow([ unicode(row[col]).encode('utf-8') for col in rs_cols ])
367
                    continue
368
                else:
369
                    exception_to = e[0]
370
                    exception_date = row['start_datetime'].date()
371
            if exception_to and EventWithAct.objects.filter(exception_to=exception_to, exception_date=exception_date):
372
                print 'exception existante', EventWithAct.objects.filter(exception_to=exception_to, exception_date=exception_date), ' ligne ', row, 'ignore'
373
                continue
374

  
375

  
376
            event = EventWithAct.objects.create(patient=row['enfant'],
377
                    start_datetime=row['start_datetime'],
378
                    end_datetime=row['end_datetime'],
379
                    act_type=row['act_type'],
380
                    old_rs_id=row['id'],
381
                    title=row['enfant'].display_name,
382
                    description=row['texte'],
383
                    exception_to=exception_to,
384
                    exception_date=exception_date)
385
            event.services = [ service ]
386
            event.participants = row['workers']
387
            print 'created', event
388

  
389

  
390
if __name__ == "__main__":
391
    main()

Also available in: Unified diff