venissieux-technocarte: handle users on a2 side and associate cards with users (#54706)

This commit is contained in:
Emmanuel Cazenave 2021-06-10 17:07:02 +02:00
parent a8b6096dea
commit 40610a86b6
1 changed files with 144 additions and 43 deletions

View File

@ -1,7 +1,7 @@
""" """
Usage : Usage :
wcs-manage runscript -d wcs.dev.publik.love run.py reset wcs-manage runscript -d wcs.dev.publik.love run.py wcs-reset
wcs-manage runscript -d wcs.dev.publik.love run.py import --filepath ~/notes/clients/venissieux/famille/technocarte.csv --wcs-api-url=https://wcs.dev.publik.love/api/ --wcs-email=admin@localhost --wcs-orig=wcs.dev.publik.love --wcs-key=c25fc1f82bd56b01e7cf62d785ae4410b0f7fdbebfb92a986d3fd6a150f3ba0e wcs-manage runscript -d wcs.dev.publik.love run.py wcs-import --filepath ~/notes/clients/venissieux/famille/technocarte.csv --api-url=https://wcs.dev.publik.love/api/ --email=admin@localhost --orig=wcs.dev.publik.love --key=c25fc1f82bd56b01e7cf62d785ae4410b0f7fdbebfb92a986d3fd6a150f3ba0e
""" """
import argparse import argparse
@ -17,6 +17,7 @@ import time
import urllib.parse import urllib.parse
import requests import requests
from requests.auth import HTTPBasicAuth
from wcs.carddef import CardDef from wcs.carddef import CardDef
CARD_ADULTE_SLUG = 'adultes' CARD_ADULTE_SLUG = 'adultes'
@ -58,16 +59,30 @@ def sign_string(s, key, algo='sha256', timedelta=30):
return hash.digest() return hash.digest()
def wcs_api_call(url, args, data=None, method='post'): def wcs_api_call(url, args, data=None, user_email=None, method='post'):
url = sign_url(url + '?email=%s' % args.wcs_email, args.wcs_key, orig=args.wcs_orig) url = sign_url(url + '?email=%s' % args.email, args.key, orig=args.orig)
if method == 'post': if method == 'post':
resp = requests.post(url, json={'data': data}) post_data = {'data': data}
if user_email:
post_data['user'] = {'email': user_email}
resp = requests.post(url, json=post_data)
elif method == 'get': elif method == 'get':
resp = requests.get(url) resp = requests.get(url)
resp.raise_for_status() resp.raise_for_status()
return resp return resp
def a2_api_call(url, args, data=None, method='post'):
if method == 'post':
resp = requests.post(url, json=data, auth=HTTPBasicAuth(args.api_user, args.api_pass))
elif method == 'get':
resp = requests.get(url, auth=HTTPBasicAuth(args.api_user, args.api_pass))
elif method == 'delete':
resp = requests.delete(url, auth=HTTPBasicAuth(args.api_user, args.api_pass))
resp.raise_for_status()
return resp
def get_field_value(carddata, varname): def get_field_value(carddata, varname):
field = None field = None
for field in carddata.formdef.get_all_fields(): for field in carddata.formdef.get_all_fields():
@ -86,6 +101,10 @@ def get_rows(args):
yield row yield row
def build_email(first_name, last_name):
return 'vpf-%s-%s@yopmail.com' % (first_name, last_name)
def init_human_data(row): def init_human_data(row):
data = { data = {
'nom': row['NOMENF'], 'nom': row['NOMENF'],
@ -109,21 +128,22 @@ def init_human_data(row):
def create_adultes(args): def create_adultes(args):
adultes = {} adultes = {}
familles_adulte_count = collections.defaultdict(int) familles_adultes = collections.defaultdict(list)
url = args.wcs_api_url + 'cards/adultes/submit' url = args.api_url + 'cards/adultes/submit'
for row in get_rows(args): for row in get_rows(args):
if row['ADULTE'] != '1': if row['ADULTE'] != '1':
continue continue
code_famille = row['CODFAM'] code_famille = row['CODFAM']
if familles_adulte_count[code_famille] >= 2: if len(familles_adultes[code_famille]) >= 2:
# gestion des doublons # gestion des doublons
continue continue
email = build_email(row['PREENF'], row['NOMENF'])
data = init_human_data(row) data = init_human_data(row)
data['telephone'] = row['NUMTEL'] data['telephone'] = row['NUMTEL']
data['courriel'] = row['MAIL'] data['courriel'] = email
data['numero_voie'] = "%s %s" % (row['NUMVOI'], row['ADRENF1']) data['numero_voie'] = "%s %s" % (row['NUMVOI'], row['ADRENF1'])
numbis = row['NUMBIS'] numbis = row['NUMBIS']
if numbis: if numbis:
@ -143,23 +163,25 @@ def create_adultes(args):
if civilite_clean: if civilite_clean:
data['civilite'] = civilite_clean data['civilite'] = civilite_clean
resp = wcs_api_call(url, args, data) resp = wcs_api_call(url, args, data=data, user_email=email)
familles_adulte_count[code_famille] += 1 adulte = {
adultes[row['CODENF']] = {
'technocarte_id': row['CODENF'], 'technocarte_id': row['CODENF'],
'publik_id': str(resp.json()['data']['id']), 'publik_id': str(resp.json()['data']['id']),
'technocarte_famille_id': code_famille, 'technocarte_famille_id': code_famille,
'nom': row['NOMENF'] 'nom': row['NOMENF'],
'email': email
} }
adultes[row['CODENF']] = adulte
familles_adultes[code_famille].append(adulte)
return adultes return adultes, familles_adultes
def create_enfants(args): def create_enfants(args, familles_adultes):
enfants = {} enfants = {}
familles_enfants = collections.defaultdict(list) familles_enfants = collections.defaultdict(list)
url = args.wcs_api_url + 'cards/%s/submit' % CARD_ENFANT_SLUG url = args.api_url + 'cards/%s/submit' % CARD_ENFANT_SLUG
for row in get_rows(args): for row in get_rows(args):
if row['ADULTE'] == '1': if row['ADULTE'] == '1':
continue continue
@ -178,9 +200,16 @@ def create_enfants(args):
if row['GRPSCO']: if row['GRPSCO']:
data['groupe_scolaire'] = row['GRPSCO'] data['groupe_scolaire'] = row['GRPSCO']
resp = wcs_api_call(url, args, data)
technocarte_famille_id = row['CODFAM'] technocarte_famille_id = row['CODFAM']
# find email of the first parent, for ownership of the card
user_email = None
for adulte in familles_adultes.get(technocarte_famille_id, []):
user_email = adulte['email']
break
resp = wcs_api_call(url, args, data, user_email=user_email)
enfant = { enfant = {
'technocarte_id': row['CODENF'], 'technocarte_id': row['CODENF'],
'publik_id': str(resp.json()['data']['id']), 'publik_id': str(resp.json()['data']['id']),
@ -199,9 +228,9 @@ def create_enfants(args):
return enfants, familles_enfants return enfants, familles_enfants
def create_familles(adultes, familles_enfants, args): def create_familles(args, adultes, familles_enfants):
familles_map = {} familles_map = {}
url = args.wcs_api_url + 'cards/%s/submit' % CARD_FAMILLE_SLUG url = args.api_url + 'cards/%s/submit' % CARD_FAMILLE_SLUG
for adulte_technocarte_id, adulte in adultes.items(): for adulte_technocarte_id, adulte in adultes.items():
technocarte_famille_id = adulte['technocarte_famille_id'] technocarte_famille_id = adulte['technocarte_famille_id']
if technocarte_famille_id not in familles_map: if technocarte_famille_id not in familles_map:
@ -219,11 +248,11 @@ def create_familles(adultes, familles_enfants, args):
if numero_allocataire_caf: if numero_allocataire_caf:
data['numero_allocataire_caf'] = numero_allocataire_caf data['numero_allocataire_caf'] = numero_allocataire_caf
url = args.wcs_api_url + 'cards/%s/submit' % CARD_FAMILLE_SLUG url = args.api_url + 'cards/%s/submit' % CARD_FAMILLE_SLUG
resp = wcs_api_call(url, args, data) resp = wcs_api_call(url, args, data, user_email=adulte['email'])
familles_map[technocarte_famille_id] = str(resp.json()['data']['id']) familles_map[technocarte_famille_id] = str(resp.json()['data']['id'])
else: else:
url = args.wcs_api_url + 'cards/%s/%s/' % ( url = args.api_url + 'cards/%s/%s/' % (
CARD_FAMILLE_SLUG, familles_map[technocarte_famille_id] CARD_FAMILLE_SLUG, familles_map[technocarte_famille_id]
) )
card = wcs_api_call(url, args, method='get').json() card = wcs_api_call(url, args, method='get').json()
@ -243,9 +272,9 @@ def create_familles(adultes, familles_enfants, args):
return familles_map return familles_map
def create_gardes(enfants, familles, args): def create_gardes(args, enfants, familles, familles_adultes):
gardes = {} gardes = {}
url = args.wcs_api_url + 'cards/%s/submit' % CARD_GARDE_SLUG url = args.api_url + 'cards/%s/submit' % CARD_GARDE_SLUG
for _, enfant in enfants.items(): for _, enfant in enfants.items():
publik_id = enfant['publik_id'] publik_id = enfant['publik_id']
technocarte_famille_id = enfant['technocarte_famille_id'] technocarte_famille_id = enfant['technocarte_famille_id']
@ -256,41 +285,113 @@ def create_gardes(enfants, familles, args):
'enfant': publik_id, 'enfant': publik_id,
'famille': publik_famille_id 'famille': publik_famille_id
} }
resp = wcs_api_call(url, args, data) # find email of the first parent, for ownership of the card
user_email = None
for adulte in familles_adultes.get(technocarte_famille_id, []):
user_email = adulte['email']
break
resp = wcs_api_call(url, args, data, user_email=user_email)
gardes[publik_id] = str(resp.json()['data']['id']) gardes[publik_id] = str(resp.json()['data']['id'])
return gardes return gardes
def import_data(args): def wcs_import_data(args):
adultes = create_adultes(args) adultes, familles_adultes = create_adultes(args)
enfants, familles_enfants = create_enfants(args) enfants, familles_enfants = create_enfants(args, familles_adultes)
familles = create_familles(adultes, familles_enfants, args) familles = create_familles(args, adultes, familles_enfants)
create_gardes(enfants, familles, args) create_gardes(args, enfants, familles, familles_adultes)
def reset(args): def a2_import_data(args):
familles_adulte_count = collections.defaultdict(int)
url = args.api_url + 'users/'
for row in get_rows(args):
if row['ADULTE'] != '1':
continue
code_famille = row['CODFAM']
if familles_adulte_count[code_famille] >= 2:
# gestion des doublons
continue
data = {
'last_name': row['NOMENF'],
'first_name': row['PREENF'],
'email': build_email(row['PREENF'], row['NOMENF']),
'send_registration_email': False
}
codsex = row['CODSEX']
if codsex == 'M':
data['gender'] = 1
elif codsex == 'F':
data['gender'] = 2
a2_api_call(url, args, data)
def a2_reset(args):
to_delete = []
url = args.api_url + 'users/'
next_ = True
while next_:
data = a2_api_call(url, args, method='get').json()
next_ = data['next']
for user in data['results']:
email, uuid = user['email'], user['uuid']
if email.startswith('vpf-') and email.endswith('yopmail.com'):
to_delete.append(uuid)
for uuid in to_delete:
url = args.api_url + 'users/%s/' % uuid
a2_api_call(url, args, method='delete')
def wcs_reset(args):
CardDef.get_by_urlname(CARD_ENFANT_SLUG).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_ADULTE_SLUG).data_class().wipe()
CardDef.get_by_urlname(CARD_FAMILLE_SLUG).data_class().wipe() CardDef.get_by_urlname(CARD_FAMILLE_SLUG).data_class().wipe()
CardDef.get_by_urlname(CARD_GARDE_SLUG).data_class().wipe() CardDef.get_by_urlname(CARD_GARDE_SLUG).data_class().wipe()
def add_import_parser_args(parser):
parser.add_argument('--filepath')
parser.add_argument('--mode', default='sample', choices=('sample', 'full'))
parser.add_argument('--sample-numlines', default=100, type=int)
return parser
def add_a2_parser_args(parser):
parser.add_argument('--api-url')
parser.add_argument('--api-user')
parser.add_argument('--api-pass')
return parser
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers() subparsers = parser.add_subparsers()
parser_import = subparsers.add_parser('import') wcs_parser_import = subparsers.add_parser('wcs-import')
parser_import.set_defaults(func=import_data) wcs_parser_import.set_defaults(func=wcs_import_data)
parser_import.add_argument('--filepath') wcs_parser_import = add_import_parser_args(wcs_parser_import)
parser_import.add_argument('--mode', default='sampleo', choices=('sample', 'full')) wcs_parser_import.add_argument('--api-url')
parser_import.add_argument('--sample-numlines', default=100, type=int) wcs_parser_import.add_argument('--email')
parser_import.add_argument('--wcs-api-url') wcs_parser_import.add_argument('--orig')
parser_import.add_argument('--wcs-email') wcs_parser_import.add_argument('--key')
parser_import.add_argument('--wcs-orig')
parser_import.add_argument('--wcs-key')
parser_import = subparsers.add_parser('reset') wcs_parser_reset = subparsers.add_parser('wcs-reset')
parser_import.set_defaults(func=reset) wcs_parser_reset.set_defaults(func=wcs_reset)
a2_parser_import = subparsers.add_parser('a2-import')
a2_parser_import.set_defaults(func=a2_import_data)
a2_parser_import = add_import_parser_args(a2_parser_import)
a2_parser_import = add_a2_parser_args(a2_parser_import)
a2_parser_reset = subparsers.add_parser('a2-reset')
a2_parser_reset.set_defaults(func=a2_reset)
a2_parser_reset = add_a2_parser_args(a2_parser_reset)
args = parser.parse_args() args = parser.parse_args()
args.func(args) args.func(args)