venissieux-technocarte: use wcs HTTP API to import data

This commit is contained in:
Emmanuel Cazenave 2021-05-27 17:57:32 +02:00
parent 3afe7267e9
commit 36aa1d99da
1 changed files with 121 additions and 74 deletions

View File

@ -1,10 +1,26 @@
import collections
import base64
import csv
import datetime
import hashlib
import hmac
import random
import sys
import time
import urllib.parse
import requests
from wcs.carddef import CardDef
CARD_ENFANT_SLUG = 'enfants'
CARD_ADULTE_SLUG = 'adultes'
CARD_FAMILLE_SLUG = 'familles'
USER = 'admin'
WCS_BASE_URL = 'https://@wcs.dev.publik.love/api/'
EMAIL = 'admin@localhost'
WCS_ORIG = 'wcs.dev.publik.love'
WCS_KEY = 'c25fc1f82bd56b01e7cf62d785ae4410b0f7fdbebfb92a986d3fd6a150f3ba0e'
FILEPATH = None
ACTION = sys.argv[1]
@ -14,18 +30,47 @@ if ACTION == 'import':
FILEPATH = sys.argv[2]
AdulteCardDef = CardDef.select(clause=lambda x: x.url_name == 'adultes')[0]
EnfantCardDef = CardDef.select(clause=lambda x: x.url_name == 'enfants')[0]
FamilleCardDef = CardDef.select(clause=lambda x: x.url_name == 'familles')[0]
def sign_url(url, key, algo='sha256', orig=None, timestamp=None, nonce=None):
parsed = urllib.parse.urlparse(url)
new_query = sign_query(parsed.query, key, algo, orig, timestamp, nonce)
return urllib.parse.urlunparse(parsed[:4] + (new_query,) + parsed[5:])
def set_field(carddata, varname, value):
field = None
for field in carddata.formdef.get_all_fields():
if field.varname == varname:
break
assert field is not None
carddata.data[field.id] = value
def sign_query(query, key, algo='sha256', orig=None, timestamp=None, nonce=None):
if timestamp is None:
timestamp = datetime.datetime.utcnow()
timestamp = timestamp.strftime('%Y-%m-%dT%H:%M:%SZ')
if nonce is None:
nonce = hex(random.getrandbits(128))[2:].rstrip('L')
new_query = query
if new_query:
new_query += '&'
new_query += urllib.parse.urlencode((('algo', algo), ('timestamp', timestamp), ('nonce', nonce)))
if orig is not None:
new_query += '&' + urllib.parse.urlencode({'orig': orig})
signature = base64.b64encode(sign_string(new_query, key, algo=algo))
new_query += '&' + urllib.parse.urlencode({'signature': signature})
return new_query
def sign_string(s, key, algo='sha256', timedelta=30):
if not isinstance(key, bytes):
key = key.encode('utf-8')
if not isinstance(s, bytes):
s = s.encode('utf-8')
digestmod = getattr(hashlib, algo)
hash = hmac.HMAC(key, digestmod=digestmod, msg=s)
return hash.digest()
def api_call(url, data=None, method='post'):
url = sign_url(url + '?email=%s' % EMAIL, WCS_KEY, orig=WCS_ORIG)
if method == 'post':
resp = requests.post(url, json={'data': data})
elif method == 'get':
resp = requests.get(url)
resp.raise_for_status()
return resp
def get_field_value(carddata, varname):
@ -46,42 +91,47 @@ def get_rows():
yield row
def init_human_data(row):
data = {
'nom': row['NOMENF'],
'prenom': row['PREENF']
}
codsex = row['CODSEX']
genre = ''
if codsex == 'M':
genre = 'Homme'
elif codsex == 'F':
genre = 'Femme'
data['genre'] = genre
if row['DATNAI']:
data['date_naissance'] = time.strftime(
'%Y-%m-%d',
time.strptime(row['DATNAI'][:10], '%d/%m/%Y')
)
return data
def create_adultes():
adultes = {}
url = WCS_BASE_URL + 'cards/adultes/submit'
for row in get_rows():
if row['ADULTE'] != '1':
continue
adulte = AdulteCardDef.data_class()()
set_field(adulte, 'nom', row['NOMENF'])
set_field(adulte, 'prenom', row['PREENF'])
codsex = row['CODSEX']
genre = ''
if codsex == 'M':
genre = 'Homme'
elif codsex == 'F':
genre = 'Femme'
set_field(adulte, 'genre', genre)
if row['DATNAI']:
set_field(adulte, 'date_naissance', time.strptime(row['DATNAI'][:10], '%d/%m/%Y'))
set_field(adulte, 'telephone', row['NUMTEL'])
set_field(adulte, 'courriel', row['MAIL'])
set_field(adulte, 'numero_voie', "%s %s" % (row['NUMVOI'], row['ADRENF1']))
set_field(adulte, 'code_postal', row['CODPOSENF'])
set_field(adulte, 'commune', row['COMMUNE'])
adulte.store()
adulte.just_created()
adulte.store()
adulte.perform_workflow()
adulte.store()
data = init_human_data(row)
data['telephone'] = row['NUMTEL']
data['courriel'] = row['MAIL']
data['numero_voie'] = "%s %s" % (row['NUMVOI'], row['ADRENF1'])
data['code_postal'] = row['CODPOSENF']
data['commune'] = row['COMMUNE']
resp = api_call(url, data)
adultes[row['CODENF']] = {
'technocarte_id': row['CODENF'],
'publik_id': adulte.id,
'technocarte_famille_id': row['CODFAM']
'publik_id': str(resp.json()['data']['id']),
'technocarte_famille_id': row['CODFAM'],
'nom': row['NOMENF']
}
return adultes
@ -89,36 +139,18 @@ def create_adultes():
def create_enfants():
enfants = {}
url = WCS_BASE_URL + 'cards/%s/submit' % CARD_ENFANT_SLUG
for row in get_rows():
if row['ADULTE'] == '1':
continue
enfant = EnfantCardDef.data_class()()
set_field(enfant, 'nom', row['NOMENF'])
set_field(enfant, 'prenom', row['PREENF'])
codsex = row['PREENF']
genre = ''
if codsex == 'M':
genre = 'Homme'
elif codsex == 'F':
genre = 'Femme'
set_field(enfant, 'genre', genre)
if row['DATNAI']:
set_field(enfant, 'date_naissance', time.strptime(row['DATNAI'][:10], '%d/%m/%Y'))
enfant.store()
enfant.just_created()
enfant.store()
enfant.perform_workflow()
enfant.store()
data = init_human_data(row)
resp = api_call(url, data)
enfant = {
'technocarte_id': row['CODENF'],
'publik_id': enfant.id,
'technocarte_famille': row['CODFAM']
'publik_id': str(resp.json()['data']['id']),
'technocarte_famille_id': row['CODFAM']
}
if row['CODPEREBIO']:
enfant['pere_technocarte_id'] = row['CODPEREBIO']
@ -131,18 +163,33 @@ def create_enfants():
def create_familles(adultes, enfants):
familles_map = {}
url = WCS_BASE_URL + 'cards/%s/submit' % CARD_FAMILLE_SLUG
for adulte_technocarte_id, adulte in adultes.items():
if 'publik_famille_id' in adulte:
# ajouter comme deuxième adulte
pass
technocarte_famille_id = adulte['technocarte_famille_id']
if technocarte_famille_id not in familles_map:
# création famille
data = {
'famille': adulte['nom'],
'adulte1': adulte['publik_id']
}
url = WCS_BASE_URL + 'cards/%s/submit' % CARD_FAMILLE_SLUG
resp = api_call(url, data)
familles_map[technocarte_famille_id] = str(resp.json()['data']['id'])
else:
publik_adulte = AdulteCardDef.data_class().select(
clause=lambda x: x.id == adulte['publik_id']
)[0]
famille = FamilleCardDef.data_class()()
set_field(famille, 'famille', get_field_value(publik_adulte, 'nom'))
famille.store()
adulte['publik_famille_id'] = famille.id
# ajouter comme deuxième adulte à la famille existante
url = WCS_BASE_URL + 'cards/%s/%s/' % (
CARD_FAMILLE_SLUG, familles_map[technocarte_famille_id]
)
data = {
'adulte2': adulte['publik_id']
}
nom_famille = api_call(url, method='get').json()['fields']['famille']
if nom_famille != adulte['nom']:
# les gens ne se marient plus
data['famille'] = "%s %s" % (nom_famille, adulte['nom'])
api_call(url, data)
def import_data():
@ -152,9 +199,9 @@ def import_data():
def reset():
AdulteCardDef.data_class().wipe()
EnfantCardDef.data_class().wipe()
FamilleCardDef.data_class().wipe()
CardDef.get_by_urlname(CARD_ENFANT_SLUG).data_class().wipe()
CardDef.get_by_urlname(CARD_ADULTE_SLUG).data_class().wipe()
CardDef.get_by_urlname(CARD_FAMILLE_SLUG).data_class().wipe()
if ACTION == 'import':