From 40610a86b6c2291535e6188f0291c5402a4941a3 Mon Sep 17 00:00:00 2001 From: Emmanuel Cazenave Date: Thu, 10 Jun 2021 17:07:02 +0200 Subject: [PATCH] venissieux-technocarte: handle users on a2 side and associate cards with users (#54706) --- venissieux-technocarte/run.py | 187 ++++++++++++++++++++++++++-------- 1 file changed, 144 insertions(+), 43 deletions(-) diff --git a/venissieux-technocarte/run.py b/venissieux-technocarte/run.py index a3cdae7..b7e6384 100644 --- a/venissieux-technocarte/run.py +++ b/venissieux-technocarte/run.py @@ -1,7 +1,7 @@ """ Usage : -wcs-manage runscript -d wcs.dev.publik.love run.py 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-reset +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 @@ -17,6 +17,7 @@ import time import urllib.parse import requests +from requests.auth import HTTPBasicAuth from wcs.carddef import CardDef CARD_ADULTE_SLUG = 'adultes' @@ -58,16 +59,30 @@ def sign_string(s, key, algo='sha256', timedelta=30): return hash.digest() -def wcs_api_call(url, args, data=None, method='post'): - url = sign_url(url + '?email=%s' % args.wcs_email, args.wcs_key, orig=args.wcs_orig) +def wcs_api_call(url, args, data=None, user_email=None, method='post'): + url = sign_url(url + '?email=%s' % args.email, args.key, orig=args.orig) 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': resp = requests.get(url) resp.raise_for_status() 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): field = None for field in carddata.formdef.get_all_fields(): @@ -86,6 +101,10 @@ def get_rows(args): yield row +def build_email(first_name, last_name): + return 'vpf-%s-%s@yopmail.com' % (first_name, last_name) + + def init_human_data(row): data = { 'nom': row['NOMENF'], @@ -109,21 +128,22 @@ def init_human_data(row): def create_adultes(args): 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): if row['ADULTE'] != '1': continue code_famille = row['CODFAM'] - if familles_adulte_count[code_famille] >= 2: + if len(familles_adultes[code_famille]) >= 2: # gestion des doublons continue + email = build_email(row['PREENF'], row['NOMENF']) data = init_human_data(row) data['telephone'] = row['NUMTEL'] - data['courriel'] = row['MAIL'] + data['courriel'] = email data['numero_voie'] = "%s %s" % (row['NUMVOI'], row['ADRENF1']) numbis = row['NUMBIS'] if numbis: @@ -143,23 +163,25 @@ def create_adultes(args): if 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 - adultes[row['CODENF']] = { + adulte = { 'technocarte_id': row['CODENF'], 'publik_id': str(resp.json()['data']['id']), '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 = {} 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): if row['ADULTE'] == '1': continue @@ -178,9 +200,16 @@ def create_enfants(args): if row['GRPSCO']: data['groupe_scolaire'] = row['GRPSCO'] - resp = wcs_api_call(url, args, data) - 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 = { 'technocarte_id': row['CODENF'], 'publik_id': str(resp.json()['data']['id']), @@ -199,9 +228,9 @@ def create_enfants(args): return enfants, familles_enfants -def create_familles(adultes, familles_enfants, args): +def create_familles(args, adultes, familles_enfants): 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(): technocarte_famille_id = adulte['technocarte_famille_id'] if technocarte_famille_id not in familles_map: @@ -219,11 +248,11 @@ def create_familles(adultes, familles_enfants, args): if numero_allocataire_caf: data['numero_allocataire_caf'] = numero_allocataire_caf - url = args.wcs_api_url + 'cards/%s/submit' % CARD_FAMILLE_SLUG - resp = wcs_api_call(url, args, data) + url = args.api_url + 'cards/%s/submit' % CARD_FAMILLE_SLUG + resp = wcs_api_call(url, args, data, user_email=adulte['email']) familles_map[technocarte_famille_id] = str(resp.json()['data']['id']) 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 = wcs_api_call(url, args, method='get').json() @@ -243,9 +272,9 @@ def create_familles(adultes, familles_enfants, args): return familles_map -def create_gardes(enfants, familles, args): +def create_gardes(args, enfants, familles, familles_adultes): 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(): publik_id = enfant['publik_id'] technocarte_famille_id = enfant['technocarte_famille_id'] @@ -256,41 +285,113 @@ def create_gardes(enfants, familles, args): 'enfant': publik_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']) return gardes -def import_data(args): - adultes = create_adultes(args) - enfants, familles_enfants = create_enfants(args) - familles = create_familles(adultes, familles_enfants, args) - create_gardes(enfants, familles, args) +def wcs_import_data(args): + adultes, familles_adultes = create_adultes(args) + enfants, familles_enfants = create_enfants(args, familles_adultes) + familles = create_familles(args, adultes, familles_enfants) + 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_ADULTE_SLUG).data_class().wipe() CardDef.get_by_urlname(CARD_FAMILLE_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() subparsers = parser.add_subparsers() -parser_import = subparsers.add_parser('import') -parser_import.set_defaults(func=import_data) -parser_import.add_argument('--filepath') -parser_import.add_argument('--mode', default='sampleo', choices=('sample', 'full')) -parser_import.add_argument('--sample-numlines', default=100, type=int) -parser_import.add_argument('--wcs-api-url') -parser_import.add_argument('--wcs-email') -parser_import.add_argument('--wcs-orig') -parser_import.add_argument('--wcs-key') +wcs_parser_import = subparsers.add_parser('wcs-import') +wcs_parser_import.set_defaults(func=wcs_import_data) +wcs_parser_import = add_import_parser_args(wcs_parser_import) +wcs_parser_import.add_argument('--api-url') +wcs_parser_import.add_argument('--email') +wcs_parser_import.add_argument('--orig') +wcs_parser_import.add_argument('--key') -parser_import = subparsers.add_parser('reset') -parser_import.set_defaults(func=reset) +wcs_parser_reset = subparsers.add_parser('wcs-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.func(args)