1 |
1 |
# -*- coding: utf-8 -*-
|
2 |
2 |
|
|
3 |
from __future__ import unicode_literals
|
|
4 |
|
3 |
5 |
import datetime
|
4 |
6 |
import six
|
5 |
7 |
import copy
|
... | ... | |
13 |
15 |
from cached_property import cached_property
|
14 |
16 |
from wcs_olap.wcs_api import WcsApiError
|
15 |
17 |
|
|
18 |
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
|
19 |
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
|
|
20 |
|
16 |
21 |
|
17 |
22 |
def quote(name):
|
18 |
23 |
return '"%s"' % name
|
... | ... | |
53 |
58 |
class WcsOlapFeeder(object):
|
54 |
59 |
|
55 |
60 |
channels = [
|
56 |
|
[1, 'web', u'web'],
|
57 |
|
[2, 'mail', u'courrier'],
|
58 |
|
[3, 'phone', u'téléphone'],
|
59 |
|
[4, 'counter', u'guichet'],
|
60 |
|
[5, 'backoffice', u'backoffice'],
|
61 |
|
[6, 'email', u'email'],
|
62 |
|
[7, 'fax', u'fax'],
|
|
61 |
[1, 'web', 'web'],
|
|
62 |
[2, 'mail', 'courrier'],
|
|
63 |
[3, 'phone', 'téléphone'],
|
|
64 |
[4, 'counter', 'guichet'],
|
|
65 |
[5, 'backoffice', 'backoffice'],
|
|
66 |
[6, 'email', 'email'],
|
|
67 |
[7, 'fax', 'fax'],
|
63 |
68 |
]
|
64 |
69 |
channel_to_id = dict((c[1], c[0]) for c in channels)
|
65 |
70 |
id_to_channel = dict((c[0], c[1]) for c in channels)
|
... | ... | |
106 |
111 |
}
|
107 |
112 |
cube = {
|
108 |
113 |
'name': 'all_formdata',
|
109 |
|
'label': u'Tous les formulaires',
|
|
114 |
'label': 'Tous les formulaires',
|
110 |
115 |
'fact_table': 'formdata',
|
111 |
116 |
'key': 'id',
|
112 |
117 |
'joins': [
|
... | ... | |
267 |
272 |
self.connection = psycopg2.connect(dsn=pg_dsn)
|
268 |
273 |
self.connection.autocommit = True
|
269 |
274 |
self.cur = self.connection.cursor()
|
270 |
|
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE, self.cur)
|
271 |
275 |
|
272 |
276 |
try:
|
273 |
277 |
self.has_jsonb = self.detect_jsonb()
|
... | ... | |
298 |
302 |
if len(table_name) < 64 and not force_hash:
|
299 |
303 |
return table_name
|
300 |
304 |
else:
|
301 |
|
return table_name[:63-hash_length] + hashlib.md5(table_name).hexdigest()[:hash_length]
|
|
305 |
return table_name[:63 - hash_length] + hashlib.md5(table_name.encode('utf-8')).hexdigest()[:hash_length]
|
302 |
306 |
|
303 |
307 |
@property
|
304 |
308 |
def default_ctx(self):
|
... | ... | |
444 |
448 |
def do_base_table(self):
|
445 |
449 |
# channels
|
446 |
450 |
self.create_labeled_table('channel', [[c[0], c[2]] for c in self.channels],
|
447 |
|
comment=u'canal')
|
|
451 |
comment='canal')
|
448 |
452 |
|
449 |
453 |
# roles
|
450 |
454 |
roles = dict((i, role.name) for i, role in enumerate(self.roles))
|
451 |
|
tmp_role_map = self.create_labeled_table('role', roles.items(), comment=u'role')
|
|
455 |
tmp_role_map = self.create_labeled_table('role', roles.items(), comment='role')
|
452 |
456 |
self.role_mapping = dict(
|
453 |
457 |
(role.id, tmp_role_map[role.name]) for role in self.roles)
|
454 |
458 |
|
455 |
459 |
# categories
|
456 |
460 |
tmp_cat_map = self.create_labeled_table(
|
457 |
|
'category', enumerate(c.name for c in self.categories), comment=u'catégorie')
|
|
461 |
'category', enumerate(c.name for c in self.categories), comment='catégorie')
|
458 |
462 |
self.categories_mapping = dict((c.id, tmp_cat_map[c.name]) for c in self.categories)
|
459 |
463 |
|
460 |
464 |
self.create_labeled_table('hour', zip(range(0, 24), map(str, range(0, 24))),
|
461 |
|
comment=u'heures')
|
|
465 |
comment='heures')
|
462 |
466 |
|
463 |
467 |
self.create_labeled_table('status', self.status,
|
464 |
|
comment=u'statuts simplifiés')
|
|
468 |
comment='statuts simplifiés')
|
465 |
469 |
self.ex('CREATE TABLE {form_table} (id serial PRIMARY KEY,'
|
466 |
470 |
' category_id integer REFERENCES {category_table} (id),'
|
467 |
471 |
' label varchar)')
|
468 |
|
self.ex('COMMENT ON TABLE {form_table} IS %s', vars=(u'types de formulaire',))
|
|
472 |
self.ex('COMMENT ON TABLE {form_table} IS %s', vars=('types de formulaire',))
|
469 |
473 |
# agents
|
470 |
|
self.create_labeled_table_serial('agent', comment=u'agents')
|
|
474 |
self.create_labeled_table_serial('agent', comment='agents')
|
471 |
475 |
|
472 |
476 |
self.columns = [
|
473 |
477 |
['id', 'serial primary key'],
|
... | ... | |
484 |
488 |
if self.has_jsonb:
|
485 |
489 |
self.columns.append(['json_data', 'JSONB NULL'])
|
486 |
490 |
self.comments = {
|
487 |
|
'formdef_id': u'formulaire',
|
488 |
|
'receipt_time': u'date de réception',
|
489 |
|
'hour_id': u'heure',
|
490 |
|
'channel_id': u'canal',
|
491 |
|
'backoffice': u'soumission backoffce',
|
492 |
|
'generic_status_id': u'statut simplifié',
|
493 |
|
'endpoint_delay': u'délai de traitement',
|
494 |
|
'geolocation_base': u'position géographique',
|
|
491 |
'formdef_id': 'formulaire',
|
|
492 |
'receipt_time': 'date de réception',
|
|
493 |
'hour_id': 'heure',
|
|
494 |
'channel_id': 'canal',
|
|
495 |
'backoffice': 'soumission backoffce',
|
|
496 |
'generic_status_id': 'statut simplifié',
|
|
497 |
'endpoint_delay': 'délai de traitement',
|
|
498 |
'geolocation_base': 'position géographique',
|
495 |
499 |
}
|
496 |
500 |
self.create_table('{generic_formdata_table}', self.columns)
|
497 |
501 |
for at, comment in self.comments.iteritems():
|
498 |
502 |
self.ex('COMMENT ON COLUMN {generic_formdata_table}.%s IS %%s' % at, vars=(comment,))
|
499 |
|
self.ex('COMMENT ON TABLE {generic_formdata_table} IS %s', vars=(u'tous les formulaires',))
|
|
503 |
self.ex('COMMENT ON TABLE {generic_formdata_table} IS %s', vars=('tous les formulaires',))
|
500 |
504 |
# evolutions
|
501 |
505 |
self.create_table('{generic_evolution_table}', [
|
502 |
506 |
['id', 'serial primary key'],
|
... | ... | |
506 |
510 |
['date', 'date'],
|
507 |
511 |
['hour_id', 'smallint REFERENCES {hour_table} (id)'],
|
508 |
512 |
])
|
509 |
|
self.ex('COMMENT ON TABLE {generic_evolution_table} IS %s', vars=(u'evolution générique',))
|
|
513 |
self.ex('COMMENT ON TABLE {generic_evolution_table} IS %s', vars=('evolution générique',))
|
510 |
514 |
|
511 |
515 |
def feed(self):
|
512 |
516 |
try:
|
... | ... | |
522 |
526 |
formdef_feeder = WcsFormdefFeeder(self, formdef, do_feed=self.do_feed)
|
523 |
527 |
formdef_feeder.feed()
|
524 |
528 |
except WcsApiError as e:
|
525 |
|
self.logger.error(u'failed to retrieve formdef %s, %s', formdef.slug, e)
|
|
529 |
self.logger.error('failed to retrieve formdef %s, %s', formdef.slug, e)
|
526 |
530 |
if 'cubes_model_dirs' in self.config:
|
527 |
531 |
model_path = os.path.join(self.config['cubes_model_dirs'], '%s.model' % self.schema)
|
528 |
532 |
with open(model_path, 'w') as f:
|
... | ... | |
597 |
601 |
statuses = self.formdef.schema.workflow.statuses
|
598 |
602 |
tmp_status_map = self.olap_feeder.create_labeled_table(
|
599 |
603 |
self.status_table_name, enumerate([s.name for s in statuses]),
|
600 |
|
comment=u'statuts du formulaire « %s »' % self.formdef.schema.name)
|
|
604 |
comment='statuts du formulaire « %s »' % self.formdef.schema.name)
|
601 |
605 |
self.status_mapping = dict((s.id, tmp_status_map[s.name]) for s in statuses)
|
602 |
606 |
|
603 |
607 |
def do_data_table(self):
|
... | ... | |
626 |
630 |
continue
|
627 |
631 |
already_seen_varnames.add(field.varname)
|
628 |
632 |
if field.type == 'item':
|
629 |
|
comment = (u'valeurs du champ « %s » du formulaire %s'
|
|
633 |
comment = ('valeurs du champ « %s » du formulaire %s'
|
630 |
634 |
% (field.label, self.formdef.schema.name))
|
631 |
635 |
table_name = self.hash_table_name('%s_field_%s' % (self.table_name, field.varname))
|
632 |
636 |
# create table and mapping
|
... | ... | |
658 |
662 |
for function, name in self.formdef.schema.workflow.functions.iteritems():
|
659 |
663 |
at = 'function_%s' % slugify(function)
|
660 |
664 |
columns.append([at, 'smallint REFERENCES {role_table} (id)'])
|
661 |
|
comments[at] = u'fonction « %s »' % name
|
|
665 |
comments[at] = 'fonction « %s »' % name
|
662 |
666 |
|
663 |
667 |
self.columns = ([name for name, _type in self.olap_feeder.columns] + [
|
664 |
668 |
name for name, _type in columns])
|
665 |
669 |
self.columns.remove('geolocation_base')
|
666 |
670 |
|
667 |
671 |
self.create_table(self.table_name, columns, inherits='{generic_formdata_table}',
|
668 |
|
comment=u'formulaire %s' % self.formdef.schema.name)
|
|
672 |
comment='formulaire %s' % self.formdef.schema.name)
|
669 |
673 |
for at, comment in comments.iteritems():
|
670 |
674 |
self.ex('COMMENT ON COLUMN {formdata_table}.%s IS %%s' % quote(at), vars=(comment,))
|
671 |
675 |
|
... | ... | |
694 |
698 |
['hour_id', 'smallint REFERENCES {hour_table} (id)'],
|
695 |
699 |
])
|
696 |
700 |
self.ex('COMMENT ON TABLE {evolution_table} IS %s',
|
697 |
|
vars=(u'evolution des demandes %s' % self.formdef.schema.name,))
|
|
701 |
vars=('evolution des demandes %s' % self.formdef.schema.name,))
|
698 |
702 |
|
699 |
703 |
def insert_item_value(self, field, value):
|
700 |
704 |
table_name = self.hash_table_name('%s_field_%s' % (self.table_name, field.varname))
|
... | ... | |
812 |
816 |
at = 'function_%s' % slugify(function)
|
813 |
817 |
row[at] = v
|
814 |
818 |
|
815 |
|
tpl = '(' + ', '.join(['%s'] * len(self.columns[1:])) + ')'
|
816 |
|
value = self.cur.mogrify(tpl, [row[column] for column in self.columns[1:]])
|
817 |
|
values.append(value)
|
|
819 |
values.append(tuple(row[column] for column in self.columns[1:]))
|
818 |
820 |
# inert evolutions
|
819 |
821 |
generic_evolution = []
|
820 |
822 |
evolution = []
|
... | ... | |
842 |
844 |
if not values:
|
843 |
845 |
self.logger.warning('no data')
|
844 |
846 |
return
|
|
847 |
insert_columns = ['%s' % quote(column) for column in self.columns[1:]]
|
|
848 |
insert_columns = ', '.join(insert_columns)
|
845 |
849 |
self.ex('INSERT INTO {formdata_table} ({columns}) VALUES {values} RETURNING id',
|
846 |
|
ctx=dict(columns=', '.join(['%s' % quote(column) for column in self.columns[1:]]), values=', '.join(values)))
|
|
850 |
ctx=dict(
|
|
851 |
columns=insert_columns,
|
|
852 |
values=', '.join(['%s'] * len(values))
|
|
853 |
),
|
|
854 |
vars=values)
|
847 |
855 |
|
848 |
856 |
# insert generic evolutions
|
849 |
857 |
generic_evolutions = []
|
... | ... | |
930 |
938 |
})
|
931 |
939 |
cube['dimensions'].append({
|
932 |
940 |
'name': at,
|
933 |
|
'label': u'fonction %s' % name.lower(),
|
|
941 |
'label': 'fonction %s' % name.lower(),
|
934 |
942 |
'join': [at],
|
935 |
943 |
'type': 'integer',
|
936 |
944 |
'value': '%s.id' % quote(at),
|
937 |
|
-
|