Doc, tools for lokavaluto development
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

460 lines
18 KiB

# coding: utf-8
from __future__ import unicode_literals
import os
import argparse
import base64
import logging
import requests
import yaml # PyYAML
from datetime import datetime
from datetime import timedelta
logging.basicConfig()
logger = logging.getLogger(__name__)
def check_request_status(r):
if r.status_code == requests.codes.ok:
logger.info('OK')
else:
logger.error(r.text)
r.raise_for_status()
# Ensemble des constantes nécessaires au fonctionnement du script.
ENV = os.environ.get('ENV')
LOCAL_CURRENCY_INTERNAL_NAME = os.environ.get('CURRENCY_SLUG')
NETWORK_INTERNAL_NAME = LOCAL_CURRENCY_INTERNAL_NAME
if ENV != 'prod':
NETWORK_INTERNAL_NAME = ENV + LOCAL_CURRENCY_INTERNAL_NAME
LOCAL_CURRENCY_SYMBOL = os.environ.get('CURRENCY_SYMBOL')
# Arguments à fournir dans la ligne de commande
parser = argparse.ArgumentParser()
parser.add_argument('url', help='URL of Cyclos')
parser.add_argument('authorization',
help='string to use for Basic Authentication')
parser.add_argument('--debug',
help='enable debug messages',
action='store_true')
args = parser.parse_args()
if not args.url.endswith('/'):
args.url = args.url + '/'
if args.debug:
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
for k, v in vars(args).items():
logger.debug('args.%s = %s', k, v)
# URLs des web services
global_web_services = args.url + 'global/web-rpc/'
network_web_services = args.url + '/' + NETWORK_INTERNAL_NAME + '/web-rpc/'
# En-têtes pour toutes les requêtes (il n'y a qu'un en-tête, pour
# l'authentification).
headers = {'Authorization': 'Basic ' + args.authorization}
# On fait une 1ère requête en lecture seule uniquement pour vérifier
# si les paramètres fournis sont corrects.
logger.info('Vérification des paramètres fournis...')
r = requests.post(global_web_services + 'network/search',
headers=headers, json={})
check_request_status(r)
########################################################################
# Création des utilisateurs pour les banques de dépôt et les comptes
# dédiés.
#
def create_user(group, name, login, email=None, password=None,city=None, custom_values=None):
logger.info('Création de l\'utilisateur "%s" (groupe "%s")...', name, group)
# FIXME code à déplacer pour ne pas l'exécuter à chaque fois
r = requests.post(network_web_services + 'group/search',
headers=headers, json={})
check_request_status(r)
groups = r.json()['result']['pageItems']
for g in groups:
if g['name'] == group:
group_id = g['id']
if not city:
city = 'Grenoble'
user_registration = {
'group': group_id,
'name': name,
'username': login,
'skipActivationEmail': True,
'addresses':[
{
'name': 'work',
'addressLine1': '10 rue du test',
'city': city,
'defaultAddress': True,
'hidden': False
}
]
}
if email:
user_registration['email'] = email
if password:
user_registration['passwords'] = [
{
'type': 'login',
'value': password,
'confirmationValue': password,
'assign': True,
'forceChange': False,
},
]
if custom_values:
user_registration['customValues'] = []
for field_id, value in custom_values.items():
r = requests.get(network_web_services + 'userCustomField/load/' + field_id, headers=headers)
check_request_status(r)
custom_field_type = r.json()['result']['type']
if custom_field_type == 'LINKED_ENTITY':
value_key = 'linkedEntityValue'
user_registration['customValues'].append({
'field': field_id,
value_key: value,
})
logger.debug('create_user : json = %s', user_registration)
r = requests.post(network_web_services + 'user/register',
headers=headers,
json=user_registration)
check_request_status(r)
logger.debug('result = %s', r.json()['result'])
user_id = r.json()['result']['user']['id']
logger.debug('user_id = %s', user_id)
return user_id
create_user(
group='Network administrators',
name= 'Administrator',
login= 'admin_network',
email= 'administrator@localhost.fr',
password= '@@bbccdd' #@WARNING : nécessité d'avoir ce mot de passe pour les tests appli CEL du Cairn
)
create_user(
group='Banques de dépôt',
name='Banque de dépôt 1',
login='BDP1',
)
create_user(
group='Banques de dépôt',
name='Banque de dépôt 2',
login='BDP2',
)
########################################################################
# Création des utilisateurs pour les tests.
if ENV != 'prod':
# On récupère l'id du champ perso 'BDC'.
r = requests.get(network_web_services + 'userCustomField/list', headers=headers)
check_request_status(r)
user_custom_fields = r.json()['result']
for field in user_custom_fields:
if field['internalName'] == 'bdc':
id_user_custom_field_bdc = field['id']
gestion_interne = {
'demo': 'Demo',
'demo2': 'Demo2',
}
for login, name in gestion_interne.items():
create_user(
group='Gestion interne',
name=name,
login=login,
password=login,
)
bureaux_de_change = {
'B000': 'Association Monnaie Locale',
'B001': 'Bureau de change 1',
'B002': 'Bureau de change 2',
}
for login, name in bureaux_de_change.items():
id_bdc = create_user(
group='Bureaux de change',
name=name + ' (BDC)',
login=login + '_BDC',
password=login,
)
create_user(
group='Opérateurs BDC',
name=name,
login=login,
password=login,
custom_values={
id_user_custom_field_bdc: id_bdc,
}
)
create_user(
group='Anonyme',
name='Anonyme',
login='anonyme',
password='anonyme',
)
adherents_utilisateurs = [
['gjanssens', 'Janssens Gaetan'],
['cretine_agnes', 'Créttine Agnès'],
['alberto_malik', 'Malik Alberto'],
['noire_aliss', 'La noire Aliss'],
['tous_andre', 'Tous Ensemble André'],
['speedy_andrew', 'Speedy Andrew'],
['stuart_andrew', 'Stuart Andrew'],
['crabe_arnold', 'Le Crabe Arnold'],
['barbare_cohen', 'le Barbare Cohen'],
['lacreuse_desiderata', 'Lacreuse Desiderata'],
['comblant_michel', 'Comblant Michel'],
['nico_faus_perso', 'Le Caméléon Nicolas'],
['benoit_perso', 'Le Rigolo Benoît'],
]
adherents_prestataires = [
['asso_mlc', 'Association Monnaie Locale','Grenoble'],
['maltobar', 'MaltOBar','Grenoble'],
['labonnepioche', 'La Bonne Pioche','Grenoble'],
['DrDBrew', 'DocteurD Brew Pub','Grenoble'],
['apogee_du_vin', 'Apogée du vin','Grenoble'],
['tout_1_fromage', 'Tout un fromage','Grenoble'],
['vie_integrative', 'vie intégrative','Voiron'],
['denis_ketels', 'Denis Ketels','Voiron'], #used only for changePassword test
['nico_faus_prod', 'Nico Faus Production','Grenoble'],
['hirundo_archi', 'Hirundo Architecture','Villard-de-Lans'],
['maison_bambous', 'Maison aux Bambous','Vinay'],
['recycleco', 'Recycleco','Saint-Marcellin'],
['elotine_photo', 'Elotine Photo','Grenoble'],
['boule_antan', 'La Boule d Antan','Villard-de-Lans'],
['la_remise', 'La Remise','Grenoble'],
['episol', 'Episol','Grenoble'],
['alter_mag', 'Alter Mag','Saint-Marcellin'],
['verre_a_soi', 'Le Verre à soi','Bilieu'],
['FluoDelik', 'Fluodélik','Méaudre'],
['1001_saveurs', '1001 Saveurs','Villard-de-Lans'],
['belle_verte', 'La Belle Verte','Susville'],
['kheops_boutique', 'Khéops boutique','Saint-Marcellin'],
['ferme_bressot', 'La ferme du Bressot','Beaulieu'],
['atelier_eltilo', 'Atelier Eltilo','Grenoble'],
['la_belle_verte', 'Belle Verte Permaculture','Sillans'],
['mon_vrac', 'Mon Vrac','Voiron'],
['le_marque_page', 'Le Marque Page','Saint-Marcellin'],
['boutik_creative', 'La Boutik Creative','Rives'],
['pain_beauvoir', 'Le Pain de Beauvoir','Beauvoir-en-Royans'],
['la_mandragore', 'La Mandragore','Grenoble'],
['jardins_epices', 'Les jardins epicés tout','Herbeys'],
['lib_colibri', 'Librairie Colibri','Voiron'],
['Claire_Dode', 'La Vie Claire Dode','Voiron'],
['fil_chantant', 'Le Fil qui Chante','Voiron'],
['epicerie_sol', 'Epicerie Solidaire Amandine','Voiron'],
['NaturaVie', 'Naturavie','Voiron'],
['montagne_arts', 'Les montagnarts','Valbonnais'],
['Biocoop', 'Biocoop','Chatte'],
['Alpes_EcoTour', 'Alpes Ecotourisme','Grenoble'],
['trankilou', 'Le Trankilou','Grenoble']
]
groupes_locaux = [
['gl_grenoble', 'Groupe Local Grenoble','Grenoble'],
['gl_voiron', 'Groupe Local Voiron','Voiron'],
['gl_tullins', 'Groupe Local Tullins','Tullins'],
]
for member in adherents_utilisateurs:
create_user(
group='Adhérents utilisateurs',
name=member[1],
login=member[0],
email = member[0] + '@test.fr',
password = '@@bbccdd',
)
create_user(
group='Adhérents utilisateurs',
name='Max Maz',
login='mazmax',
email = 'maxime.mazouth-laurol@cairn-monnaie.com',
password = '@@bbccdd',
)
for member in adherents_prestataires:
create_user(
group='Adhérents prestataires',
name=member[1],
login=member[0],
email = member[0] + '@test.fr',
city = member[2],
password = '@@bbccdd',
)
for member in groupes_locaux:
create_user(
group='Network administrators',
name=member[1],
login=member[0],
email = member[0] + '@test.fr',
city = member[2],
password = '@@bbccdd',
)
porteurs = {
'P001': 'Porteur 1',
'P002': 'Porteur 2',
'P003': 'Porteur 3',
'P004': 'Porteur 4',
}
for login, name in porteurs.items():
create_user(
group='Porteurs',
name=name,
login=login,
)
# Récupération des constantes
logger.info('Récupération des constantes depuis le YAML...')
CYCLOS_CONSTANTS = None
with open("/cyclos/cyclos_constants_"+ENV+".yml", 'r') as cyclos_stream:
try:
CYCLOS_CONSTANTS = yaml.load(cyclos_stream)
except yaml.YAMLError as exc:
assert False, exc
# Impression billets mlc
logger.info('Impression billets '+ LOCAL_CURRENCY_INTERNAL_NAME +'...')
logger.debug(str(CYCLOS_CONSTANTS['payment_types']['impression_de_billets_mlc']) + "\r\n" +
str(CYCLOS_CONSTANTS['currencies']['mlc']) + "\r\n" +
str(CYCLOS_CONSTANTS['account_types']['compte_de_debit_mlc_billet']) + "\r\n" +
str(CYCLOS_CONSTANTS['account_types']['stock_de_billets']))
r = requests.post(network_web_services + 'payment/perform',
headers={'Authorization': 'Basic {}'.format(base64.standard_b64encode(b'demo:demo').decode('utf-8'))}, # noqa
json={
'type': CYCLOS_CONSTANTS['payment_types']['impression_de_billets_mlc'],
'amount': 126500,
'currency': CYCLOS_CONSTANTS['currencies']['mlc'],
'from': 'SYSTEM',
'to': 'SYSTEM',
})
logger.info('Impression billets ' + LOCAL_CURRENCY_INTERNAL_NAME + '... Terminé !')
logger.debug(r.json())
#@WARNING : specifique au cairn, à supprimer dans le rendu au mvt Sol
today = datetime.now()
def date_modify(nb_days):
today = datetime.now()
date = today + timedelta(days=nb_days)
return date.strftime("%Y")+ '-' + date.strftime("%m")+'-'+date.strftime("%d")
def credit_numeric_money_safe(amount):
logger.info('Creation de MLC numeriques ...')
r = requests.post(network_web_services + 'payment/perform',
headers={'Authorization': 'Basic {}'.format(base64.standard_b64encode(b'admin_network:@@bbccdd').decode('utf-8'))},
json={
'type': CYCLOS_CONSTANTS['payment_types']['creation_mlc_numeriques'],
'amount': amount,
'currency': CYCLOS_CONSTANTS['currencies']['mlc'],
'from': 'SYSTEM',
'to': 'SYSTEM',
'description': 'creation initiale de ' + LOCAL_CURRENCY_INTERNAL_NAME ,
})
logger.info('Creation de MLC numeriques... Terminé !')
logger.debug(r.json())
def credit_de_compte(member,amount):
logger.info('Change numérique pour ' + member[1] + ' ...')
r = requests.post(network_web_services + 'payment/perform',
headers={'Authorization': 'Basic {}'.format(base64.standard_b64encode(b'admin_network:@@bbccdd').decode('utf-8'))},
json={
'type': CYCLOS_CONSTANTS['payment_types']['credit_du_compte'],
'amount': amount,
'currency': CYCLOS_CONSTANTS['currencies']['mlc'],
'from': 'SYSTEM',
'to': member[0],
'description': 'dépôt ' + LOCAL_CURRENCY_INTERNAL_NAME ,
'customValues': [
{
'field': str(CYCLOS_CONSTANTS['transaction_custom_fields']['bdc']),
'linkedEntityValue': id_bdc # ID de l'utilisateur Bureau de change
},
]
})
logger.info('Change numérique pour ' + member[1] + '... Terminé !')
logger.debug(r.json())
def payment_inter_adherent(debitor, creditor, amount, offset):
logger.info('Virement de ' + str(amount) + ' ' + LOCAL_CURRENCY_INTERNAL_NAME + ' ' + debitor + ' vers ' + creditor + ' ...')
if offset == 0:
cyclos_method = 'payment/perform'
else:
cyclos_method = 'scheduledPayment/perform'
r = requests.post(network_web_services + cyclos_method,
headers={'Authorization': 'Basic {}'.format(base64.standard_b64encode(b'admin_network:@@bbccdd').decode('utf-8'))},
json={
'type': CYCLOS_CONSTANTS['payment_types']['virement_inter_adherent'],
'amount': amount,
'currency': CYCLOS_CONSTANTS['currencies']['mlc'],
'description': 'virement ' + LOCAL_CURRENCY_INTERNAL_NAME ,
'firstInstallmentDate': date_modify(offset),
'installmentsCount': 1,
'from': debitor,
'to': creditor,
})
logger.info('Virement de ' + str(amount) + ' ' + LOCAL_CURRENCY_INTERNAL_NAME + ' ' + debitor + ' vers ' + creditor + ' ... Terminé !')
logger.debug(r.json())
#Creation initiale de MLC numeriques
credit_numeric_money_safe(10000000000)
# Changes numériques afin d'avoir des comptes avec des soldes non nuls + des opérations à injecter dans l'appli CEL
logger.info('Changes numériques en '+ LOCAL_CURRENCY_INTERNAL_NAME +' pour tous les pros à Grenoble...')
logger.debug(str(CYCLOS_CONSTANTS['payment_types']['credit_du_compte']) + "\r\n" +
str(CYCLOS_CONSTANTS['account_types']['compte_de_debit_mlc_numerique']) + "\r\n" +
str(CYCLOS_CONSTANTS['account_types']['compte_d_adherent']))
initial_credit = 1000
for pro in adherents_prestataires:
if pro[2] == 'Grenoble':
credit_de_compte(pro, initial_credit)
for person in adherents_utilisateurs:
credit_de_compte(person, initial_credit)
logger.info('Changes numériques en ' + LOCAL_CURRENCY_INTERNAL_NAME + '... Terminé !')
logger.info('Virements immédiats de compte à compte en '+ LOCAL_CURRENCY_INTERNAL_NAME +' ...')
#trankilou has null account again
logger.info('"Le Trankilou" réalise un virement vers "la Remise" remettant son solde à 0')
payment_inter_adherent('trankilou','la_remise',initial_credit,0)
# for i in range(0,10):
# payment_inter_adherent('DrDBrew','apogee_du_vin',10,0)
logger.info('Virements immédiats de compte à compte en '+ LOCAL_CURRENCY_INTERNAL_NAME +'... Terminé !')
logger.info('Virements programmés en '+ LOCAL_CURRENCY_INTERNAL_NAME +' de La Bonne Pioche vers AlterMag...')
for i in range(0,5):
payment_inter_adherent('labonnepioche','alter_mag',10,2)
logger.info('Virements programmés en '+ LOCAL_CURRENCY_INTERNAL_NAME +' ... Terminé !!')
logger.info('Fin du script !')