def create_transfer_account_user(test_client, init_database): from server.utils.user import create_transfer_account_user user = create_transfer_account_user(first_name='Tristan', last_name='Cole', phone='0401391419') db.session.commit() return user
def create_user_with_existing_transfer_account(test_client, init_database, create_transfer_account): from server.utils.user import create_transfer_account_user user = create_transfer_account_user(first_name='Existing Transfer', last_name='User', phone=fake.msisdn(), existing_transfer_account=create_transfer_account) db.session.commit() return user
def get_or_create_transfer_user(email, business_usage, organisation): user = User.query.filter_by( email=str(email).lower()).first() if user: return user else: first_name = random.choice(['Magnificent', 'Questionable', 'Bold', 'Hungry', 'Trustworthy', 'Valued', 'Free', 'Obtuse', 'Frequentist', 'Long', 'Sinister', 'Happy', 'Safe', 'Open', 'Cool']) last_name = random.choice(['Panda', 'Birb', 'Doggo', 'Otter', 'Swearwolf', 'Kitty', 'Lion', 'Chimp', 'Cthulhu']) is_beneficiary = random.choice([True, False]) phone = '+1' + ''.join([str(random.randint(0,10)) for i in range(0, 10)]) user = create_transfer_account_user( first_name=first_name, last_name=last_name, email=email, phone=phone, organisation=organisation, is_beneficiary=is_beneficiary, is_vendor=not is_beneficiary ) user.business_usage = business_usage return user
def create_transfer_account_user(test_client, init_database, create_organisation): from server.utils.user import create_transfer_account_user user = create_transfer_account_user(first_name='Transfer', last_name='User', phone=fake.msisdn(), organisation=create_organisation) db.session.commit() return user
def test_prep_bulk_disbursement_api(test_client, complete_admin_auth_token, create_organisation): # This is a hack because the test DB isn't being built with migrations (and thus doesn't have trigrams) db.session.execute(''' CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE INDEX trgm_first_name ON "user" USING gist (first_name gist_trgm_ops); CREATE INDEX trgm_last_name ON "user" USING gist (last_name gist_trgm_ops); CREATE INDEX trgm_phone ON "user" USING gist (_phone gist_trgm_ops); CREATE INDEX trgm_public_serial_number ON "user" USING gist (_public_serial_number gist_trgm_ops); CREATE INDEX trgm_primary_blockchain_address ON "user" USING gist (primary_blockchain_address gist_trgm_ops); CREATE INDEX trgm_location ON "user" USING gist (_location gist_trgm_ops); ''') # Adds users we're searching for create_transfer_account_user(first_name='Michiel', last_name='deRoos', phone='+19025551234', organisation=create_organisation, initial_disbursement=100).location = 'Halifax' create_transfer_account_user( first_name='Francine', last_name='deRoos', phone='+19025552345', organisation=create_organisation, initial_disbursement=200).location = 'Dartmouth' create_transfer_account_user(first_name='Roy', last_name='Donk', phone='+12345678901', organisation=create_organisation, initial_disbursement=200).location = 'Burbank' create_transfer_account_user( first_name='Paul', last_name='Bufano', phone='+98765432123', organisation=create_organisation, initial_disbursement=200).location = 'California' db.session.commit()
def test_create_bulk_credit_transfer(test_client, authed_sempo_admin_user, create_transfer_account_user, create_credit_transfer, is_bulk, invert_recipient_list, transfer_amount, transfer_type, status_code): from server.utils.user import create_transfer_account_user from flask import g # Create admin user and auth authed_sempo_admin_user.set_held_role('ADMIN', 'superadmin') auth = get_complete_auth_token(authed_sempo_admin_user) g.active_organisation = authed_sempo_admin_user.default_organisation # Create 15 users to test against users = [] user_ids = [] for _ in range(15): user = create_transfer_account_user( organisation=authed_sempo_admin_user.default_organisation) db.session.commit() users.append(user) user_ids.append(user.id) # Create set subset of created users to disburse to (first 5 users) recipients = [10, 11, 12, 13] response = test_client.post( '/api/v1/credit_transfer/', headers=dict(Authorization=auth, Accept='application/json'), data=json.dumps( dict( is_bulk=is_bulk, recipient_transfer_accounts_ids=recipients, invert_recipient_list=invert_recipient_list, transfer_amount=transfer_amount, transfer_type=transfer_type, )), content_type='application/json', follow_redirects=True) db.session.commit() # Get IDs for every user disbursed to, then check that the list matches up # with the list of recipients (or the inverse if invert_recipient_list) rx_ids = [] for transfer in response.json['data']['credit_transfers']: rx_ids.append(transfer['recipient_transfer_account']['id']) if invert_recipient_list: for id in rx_ids: assert id not in recipients else: assert rx_ids == recipients
def prep_search_api(test_client, complete_admin_auth_token, create_organisation): # This is a hack because the test DB isn't being built with migrations (and thus doesn't have tsvectors) db.session.execute("drop table search_view;") db.session.commit() db.session.execute(''' CREATE MATERIALIZED VIEW search_view AS ( SELECT u.id, u.email, u._phone, u.first_name, u.last_name, u._public_serial_number, u._location, u.primary_blockchain_address, u.default_transfer_account_id, to_tsvector(u.email) AS tsv_email, to_tsvector(u._phone) AS tsv_phone, to_tsvector(u.first_name) AS tsv_first_name, to_tsvector(u.last_name) AS tsv_last_name, to_tsvector(u._public_serial_number) AS tsv_public_serial_number, to_tsvector(u._location) AS tsv_location, to_tsvector(u.primary_blockchain_address) AS tsv_primary_blockchain_address, to_tsvector(CAST (u.default_transfer_account_id AS VARCHAR(10))) AS tsv_default_transfer_account_id FROM "user" u ); ''') # Adds users we're searching for create_transfer_account_user(first_name='Michiel', last_name='deRoos', phone="+19025551234", organisation=create_organisation, initial_disbursement=100) create_transfer_account_user(first_name='Francine', last_name='deRoos', phone="+19025552345", organisation=create_organisation, initial_disbursement=200) create_transfer_account_user(first_name='Roy', last_name='Donk', phone="+19025553456", organisation=create_organisation, initial_disbursement=200) db.session.commit() # Manually refresh tsvectors because the test DB has no triggers either db.session.execute("REFRESH MATERIALIZED VIEW search_view;")
def test_credit_transfer_internal_callback(mocker, test_client, authed_sempo_admin_user, create_organisation, new_credit_transfer): # For this, we want to test 5 permutations of third-party transactions to add: # 1. Existing User A -> Existing User B # 2. Existing User A -> Stranger A # 3. Existing User A -> Stranger A (to ensure we don't give Stranger A two ghost accounts) # 4. Stranger B -> Existing User A # 5. Idempotency check (repeat step 4's request, ensure only one transfer is created) # 6. Stranger A -> Stranger B To ensure we're not tracking transactions between strangers who are in the system # (Do nothing-- we don't care about transfers between strangers who aren't members) # 7. Stranger C -> Stranger D To ensure we're not tracking transactions between strangers who are NOT in the system # (Do nothing-- we don't care about transfers between strangers who aren't members) # 8. Existing Credit Transfer. 200 response, and received_third_party_sync becomes True send_to_worker_called = [] def mock_send_blockchain_payload_to_worker(is_retry=False, queue='high_priority'): send_to_worker_called.append([is_retry, queue]) mocker.patch( 'server.models.credit_transfer.CreditTransfer.send_blockchain_payload_to_worker', mock_send_blockchain_payload_to_worker) # Util function to POST to internal credit_transfer, since we'll be doing that a lot def post_to_credit_transfer_internal(sender_blockchain_address, recipient_blockchain_address, blockchain_transaction_hash, transfer_amount, contract_address): basic_auth = 'Basic ' + base64.b64encode( bytes( config.INTERNAL_AUTH_USERNAME + ":" + config.INTERNAL_AUTH_PASSWORD, 'ascii')).decode('ascii') return test_client.post( '/api/v1/credit_transfer/internal/', headers=dict(Authorization=basic_auth, Accept='application/json'), data=json.dumps( dict( sender_blockchain_address=sender_blockchain_address, recipient_blockchain_address=recipient_blockchain_address, blockchain_transaction_hash=blockchain_transaction_hash, transfer_amount=transfer_amount, contract_address=contract_address, )), content_type='application/json', follow_redirects=True) org = create_organisation token = org.token # 1. Existing User A -> Existing User B existing_user_a = create_transfer_account_user(first_name='Arthur', last_name='Read', phone="+19025551234", organisation=org, initial_disbursement=100) existing_user_a.default_transfer_account.set_balance_offset(1000) existing_user_b = create_transfer_account_user(first_name='Buster', last_name='Baxter', phone="+19025554321", organisation=org, initial_disbursement=100) existing_user_b.default_transfer_account.set_balance_offset(1000) made_up_hash = '0xdeadbeef2322d396649ed2fa2b7e0a944474b65cfab2c4b1435c81bb16697ecb' resp = post_to_credit_transfer_internal( existing_user_a.default_transfer_account.blockchain_address, existing_user_b.default_transfer_account.blockchain_address, made_up_hash, 100, token.address) assert resp.json['data']['credit_transfer']['sender_transfer_account'][ 'id'] == existing_user_a.default_transfer_account.id assert resp.json['data']['credit_transfer']['recipient_transfer_account'][ 'id'] == existing_user_b.default_transfer_account.id transfer_id = resp.json['data']['credit_transfer']['id'] transfer = CreditTransfer.query.filter_by( id=transfer_id).execution_options(show_all=True).first() assert transfer.sender_transfer_account == existing_user_a.default_transfer_account assert transfer.recipient_transfer_account == existing_user_b.default_transfer_account # Check that the user is being attached too assert transfer.sender_user_id == existing_user_a.id assert transfer.recipient_user_id == existing_user_b.id # 2. Existing User A -> Stranger A fake_user_a_address = '0xA9450d3dB5A909b08197BC4a0665A4d632539739' made_up_hash = '0x0000beef2322d396649ed2fa2b7e0a944474b65cfab2c4b1435c81bb16697ecb' resp = post_to_credit_transfer_internal( existing_user_a.default_transfer_account.blockchain_address, fake_user_a_address, made_up_hash, 100, token.address) assert resp.json['data']['credit_transfer']['sender_transfer_account'][ 'id'] == existing_user_a.default_transfer_account.id assert resp.json['data']['credit_transfer']['recipient_transfer_account'][ 'id'] != existing_user_b.default_transfer_account.id assert resp.json['data']['credit_transfer']['recipient_transfer_account'][ 'id'] != existing_user_a.default_transfer_account.id stranger_a_id = resp.json['data']['credit_transfer'][ 'recipient_transfer_account']['id'] transfer_id = resp.json['data']['credit_transfer']['id'] transfer = CreditTransfer.query.filter_by( id=transfer_id).execution_options(show_all=True).first() assert transfer.sender_transfer_account == existing_user_a.default_transfer_account assert transfer.recipient_transfer_account.blockchain_address == fake_user_a_address assert transfer.recipient_transfer_account.account_type == TransferAccountType.EXTERNAL assert transfer.sender_user_id == existing_user_a.id # Check that a blockchain task isn't created for outside transactions assert transfer.blockchain_task_uuid == None # Check that a transfer made through TX sync can't be resolved as completed with pytest.raises(Exception): transfer.resolve_as_complete() # 3. Existing User A -> Stranger A (to ensure we don't give Stranger A two ghost accounts) made_up_hash = '0x000011112322d396649ed2fa2b7e0a944474b65cfab2c4b1435c81bb16697ecb' resp = post_to_credit_transfer_internal( existing_user_a.default_transfer_account.blockchain_address, fake_user_a_address, made_up_hash, 100, token.address) assert resp.json['data']['credit_transfer']['sender_transfer_account'][ 'id'] == existing_user_a.default_transfer_account.id assert resp.json['data']['credit_transfer']['recipient_transfer_account'][ 'id'] == stranger_a_id transfer_id = resp.json['data']['credit_transfer']['id'] transfer = CreditTransfer.query.filter_by( id=transfer_id).execution_options(show_all=True).first() assert transfer.sender_transfer_account == existing_user_a.default_transfer_account assert transfer.recipient_transfer_account.blockchain_address == fake_user_a_address assert transfer.recipient_transfer_account.account_type == TransferAccountType.EXTERNAL assert transfer.sender_user_id == existing_user_a.id # 4. Stranger B -> Existing User A fake_user_b_address = '0xA9450d3dB5A909b08197BC4a0665A4d632539739' made_up_hash = '0x2222beef2322d396649ed2fa2b7e0a944474b65cfab2c4b1435c81bb16697ecb' resp = post_to_credit_transfer_internal( fake_user_b_address, existing_user_a.default_transfer_account.blockchain_address, made_up_hash, 100, token.address) assert resp.json['data']['credit_transfer']['recipient_transfer_account'][ 'id'] == existing_user_a.default_transfer_account.id stranger_a_id = resp.json['data']['credit_transfer'][ 'recipient_transfer_account']['id'] transfer_id = resp.json['data']['credit_transfer']['id'] transfer = CreditTransfer.query.filter_by( id=transfer_id).execution_options(show_all=True).first() assert transfer.recipient_transfer_account == existing_user_a.default_transfer_account assert transfer.sender_transfer_account.blockchain_address == fake_user_b_address assert transfer.sender_transfer_account.account_type == TransferAccountType.EXTERNAL # 5. Idempotency check (repeat step 4's request, ensure only one transfer is created) resp_two = post_to_credit_transfer_internal( fake_user_b_address, existing_user_a.default_transfer_account.blockchain_address, made_up_hash, 100, token.address) assert resp.json['data']['credit_transfer']['id'] == resp_two.json['data'][ 'credit_transfer']['id'] # 6. Stranger B -> Stranger A (Strangers who exist in the system) made_up_hash = '0x2222b33f1322d396649ed2fa2b7e0a944474b65cfab2c4b1435c81bb16697ecb' resp = post_to_credit_transfer_internal(fake_user_b_address, fake_user_a_address, made_up_hash, 100, token.address) assert resp.json[ 'message'] == 'Only external users involved in this transfer' # 7. Stranger C -> Stranger D (Strangers who do NOT exist in the system) made_up_hash = '0x2222b33f13288396649ed2fa2b7e0a944123b65cfab2c4b1435c81bb16697ecb' fake_user_c_address = '0xA9450d3dB5A909b08197BC4a0665A4d632539111' fake_user_d_address = '0xA9450d3dB5A909b08197BC4a0665A4d632539222' resp = post_to_credit_transfer_internal(fake_user_c_address, fake_user_d_address, made_up_hash, 100, token.address) assert resp.json[ 'message'] == 'No existing users involved in this transfer' # 8. Stranger A -> Stranger E (One existing stanger, one new stranger) made_up_hash = '0x2222b33f13288396649ed2fffb7e0a944123b65cfab2c4b1435c81bb16697ecb' fake_user_e_address = '0xA9450d3dB5A909b08197BC4a0665A4d63253aaaf' resp = post_to_credit_transfer_internal(fake_user_a_address, fake_user_e_address, made_up_hash, 100, token.address) assert resp.json[ 'message'] == 'Only external users involved in this transfer' # 9. Stranger E -> Stranger A (One new stranger, one existing stanger) made_up_hash = '0x2222b33f13288396649ed2fffb7e0a944123b65cfab2c4b1435c81bb12697ecb' fake_user_e_address = '0xA9450d3dB5A909b08197BC4a0665A4d63253aaaf' resp = post_to_credit_transfer_internal(fake_user_e_address, fake_user_a_address, made_up_hash, 100, token.address) assert resp.json[ 'message'] == 'Only external users involved in this transfer' # Make sure we're not sending any of the tranfers off to the blockchain assert len(send_to_worker_called) == 0 from flask import g assert len(g.pending_transactions) == 0
def generate_timeseries_metrics(create_organisation): # Generates metrics over timeline # User1 and User2 made today user1 = create_transfer_account_user(first_name='Ricky', phone="+19025551234", organisation=create_organisation, roles=[('BENEFICIARY', 'beneficiary') ]) user1.created = zero_time user1.default_transfer_account.is_approved = True user1.default_transfer_account._make_initial_disbursement(100, True) user1._location = 'Sunnyvale' attribute_dict = {'custom_attributes': {}} attribute_dict['custom_attributes']['colour'] = 'red' attribute_dict['custom_attributes']['chips'] = 'Dressed All Over' set_custom_attributes(attribute_dict, user1) user1.lat = 44.675447 user1.lng = -63.594995 user2 = create_transfer_account_user(first_name='Bubbles', phone="+19025551235", organisation=create_organisation) user2.created = zero_time user2.default_transfer_account.is_approved = True user2.default_transfer_account._make_initial_disbursement(200, True) user2._location = 'Sunnyvale' attribute_dict = {'custom_attributes': {}} attribute_dict['custom_attributes']['colour'] = 'red' attribute_dict['custom_attributes']['chips'] = 'Chicken' user2.lat = 44.675447 user2.lng = -63.594995 set_custom_attributes(attribute_dict, user2) # user3 made yesterday user3 = create_transfer_account_user(first_name='Julian', phone="+19025531230", organisation=create_organisation) user3.default_transfer_account.is_approved = True disburse = user3.default_transfer_account._make_initial_disbursement( 210, True) user3.created = zero_time user3.created = user3.created - timedelta(days=1) + timedelta(hours=6) disburse.created = user3.created - timedelta(days=1) + timedelta(hours=3) user3._location = 'Dartmouth' attribute_dict = {'custom_attributes': {}} attribute_dict['custom_attributes']['colour'] = 'blue' attribute_dict['custom_attributes']['chips'] = 'Barbecue' set_custom_attributes(attribute_dict, user3) user3.lat = 44.668055 user3.lng = -63.580829 # user4 made 4 days ago user4 = create_transfer_account_user(first_name='Randy', phone="+19025511230", organisation=create_organisation) user4.created = zero_time user4.default_transfer_account.is_approved = True disburse = user4.default_transfer_account._make_initial_disbursement( 201, True) user4.created = user4.created - timedelta(days=4) + timedelta(hours=23) disburse.created = user4.created - timedelta(days=4) + timedelta(hours=1) user4._location = 'Lower Sackville' attribute_dict = {'custom_attributes': {}} attribute_dict['custom_attributes']['colour'] = 'blue' attribute_dict['custom_attributes']['chips'] = 'Barbecue' set_custom_attributes(attribute_dict, user4) user4.lat = 44.770061 user4.lng = -63.692723 # user5/user6 made 10 days ago user5 = create_transfer_account_user(first_name='Cory', phone="+19011531230", organisation=create_organisation) user5.created = zero_time user5.default_transfer_account.is_approved = True disburse = user5.default_transfer_account._make_initial_disbursement( 202, True) user5.created = user5.created - timedelta(days=10) + timedelta(hours=2) disburse.created = user5.created - timedelta(days=10) + timedelta(hours=5) user5._location = 'Truro' attribute_dict = {'custom_attributes': {}} attribute_dict['custom_attributes']['colour'] = 'green' attribute_dict['custom_attributes']['chips'] = 'Dressed All Over' set_custom_attributes(attribute_dict, user5) user5.lat = 45.368075 user5.lng = -63.256207 user6 = create_transfer_account_user(first_name='Trevor', phone="+19025111230", organisation=create_organisation) user6.created = zero_time user6.default_transfer_account.is_approved = True disburse = user6.default_transfer_account._make_initial_disbursement( 204, True) attribute_dict = {'custom_attributes': {}} attribute_dict['custom_attributes']['colour'] = 'red' attribute_dict['custom_attributes']['chips'] = 'Jalapeno' set_custom_attributes(attribute_dict, user6) user6.lat = 44.368363 user6.lng = -64.526330 db.session.commit() tu1 = TransferUsage.find_or_create("Pepperoni") tu2 = TransferUsage.find_or_create("Jalepeno Chips") tu3 = TransferUsage.find_or_create("Shopping Carts") tu1.created = zero_time - timedelta(days=15) + timedelta(hours=22) tu2.created = zero_time - timedelta(days=15) + timedelta(hours=2) tu3.created = zero_time - timedelta(days=15) + timedelta(hours=1) p1 = make_payment_transfer( 100, create_organisation.token, send_user=user1, send_transfer_account=user1.default_transfer_account, receive_user=user2, receive_transfer_account=user2.default_transfer_account, transfer_use=str(int(tu1.id))) p1.created = zero_time + timedelta(hours=3) p2 = make_payment_transfer( 25, create_organisation.token, send_user=user3, send_transfer_account=user3.default_transfer_account, receive_user=user4, receive_transfer_account=user4.default_transfer_account, transfer_use=str(int(tu1.id))) p2.created = zero_time p2.created = p2.created - timedelta(days=1) + timedelta(hours=7) p3 = make_payment_transfer( 5, create_organisation.token, send_user=user4, send_transfer_account=user4.default_transfer_account, receive_user=user2, receive_transfer_account=user2.default_transfer_account, transfer_use=str(int(tu2.id))) p3.created = zero_time p3.created = p3.created - timedelta(days=1) + timedelta(hours=22) p4 = make_payment_transfer( 20, create_organisation.token, send_user=user5, send_transfer_account=user5.default_transfer_account, receive_user=user6, receive_transfer_account=user6.default_transfer_account, transfer_use=str(int(tu3.id))) p4.created = zero_time p4.created = p4.created - timedelta(days=4) + timedelta(hours=1) p5 = make_payment_transfer( 20, create_organisation.token, send_user=user6, send_transfer_account=user6.default_transfer_account, receive_user=user5, receive_transfer_account=user5.default_transfer_account, transfer_use=str(int(tu2.id))) p5.created = zero_time p5.created = p5.created - timedelta(days=6) + timedelta(hours=23) db.session.commit()
def insert_user(self, ge_user): phone_number = None if 'DELETED' in ge_user['phone'] else ge_user[ 'phone'] if not phone_number: print("Phone Deleted, Skipping") return if ge_user['status'] == 'Deleted': print("User Deleted, Skipping") return processed_phone = proccess_phone_number(phone_number) existing_user = User.query.filter_by( phone=processed_phone).execution_options(show_all=True).first() if existing_user: print(f'User already exists for phone {processed_phone}') return business_usage = None if ge_user.get('business_type') is not None: sempo_category = GE_BUSINESS_CATEGORY_MAPPINGS.get( ge_user['business_type']) if sempo_category: business_usage = TransferUsage.query.filter_by( name=sempo_category).first() organsation = db.session.query(Organisation).get( self.sempo_organisation_id) try: sempo_user = create_transfer_account_user( first_name=ge_user['first_name'], last_name=ge_user['last_name'], organisation=organsation, phone=phone_number, preferred_language=ge_user['preferred_language'], location=ge_user['location'], business_usage=business_usage) sempo_user.pin_hash = ge_user['encrypted_pin'] sempo_user.is_activated = ge_user[ 'status'] == 'Active' # Is this the correct way to find this out? sempo_user.default_transfer_account.is_approved = True sempo_user.is_disabled = False sempo_user.is_phone_verified = True sempo_user.is_self_sign_up = False sempo_user.terms_accepted = False sempo_user.created = ge_user['created_at'] sempo_user.is_market_enabled = int(ge_user['market_enabled']) == 1 sempo_user.custom_attributes = self.create_custom_attributes( ge_user) if ge_user['token_agents.id'] is not None: sempo_user.set_held_role('TOKEN_AGENT', 'grassroots_token_agent') else: # Is this the correct way to find this out or can a benificiary also be a token agent # Or is there some field where you can find this out? sempo_user.set_held_role('BENEFICIARY', 'beneficiary') if ge_user['group_accounts.id'] is not None: sempo_user.set_held_role('GROUP_ACCOUNT', 'grassroots_group_account') db.session.flush() return sempo_user except (IntegrityError, InvalidRequestError) as e: print(e) db.session().rollback()
def test_search_api(test_client, complete_admin_auth_token, create_organisation): """ When the '/api/v1/search/' page is requested with search parameters check that the results are in the correct order """ # This is a hack because the test DB isn't being built with migrations (and thus doesn't have tsvectors) db.session.execute("drop table search_view;") db.session.commit() db.session.execute(''' CREATE MATERIALIZED VIEW search_view AS ( SELECT u.id, u.email, u._phone, u.first_name, u.last_name, u._public_serial_number, u._location, u.primary_blockchain_address, u.default_transfer_account_id, to_tsvector(u.email) AS tsv_email, to_tsvector(u._phone) AS tsv_phone, to_tsvector(u.first_name) AS tsv_first_name, to_tsvector(u.last_name) AS tsv_last_name, to_tsvector(u._public_serial_number) AS tsv_public_serial_number, to_tsvector(u._location) AS tsv_location, to_tsvector(u.primary_blockchain_address) AS tsv_primary_blockchain_address, to_tsvector(CAST (u.default_transfer_account_id AS VARCHAR(10))) AS tsv_default_transfer_account_id FROM "user" u ); ''') # Adds users we're searching for create_transfer_account_user(first_name='Michiel', last_name='deRoos', phone="+19025551234", organisation=create_organisation) create_transfer_account_user(first_name='Francine', last_name='deRoos', phone="+19025552345", organisation=create_organisation) create_transfer_account_user(first_name='Roy', last_name='Donk', phone="+19025553456", organisation=create_organisation) db.session.commit() # Manually refresh tsvectors because the test DB has no triggers either db.session.execute("REFRESH MATERIALIZED VIEW search_view;") expected_results = { '': ['Roy', 'Francine', 'Michiel'], # Empty string should return everyone 'fra': ['Francine'], # Only user starting with 'fra' substring is Francine 'fra der': [ 'Francine', "Michiel" ], # 'fra der' should return Francine first. Michiel 2nd, because it still matches _something_ 'mic der': [ 'Michiel', "Francine" ] # 'fra der' should return Michiel first. Francine 2nd, because it still matches _something_ } for e in expected_results: response = test_client.get( '/api/v1/search/?search_string={}&search_type=transfer_accounts'. format(e), headers=dict(Authorization=complete_admin_auth_token, Accept='application/json'), follow_redirects=True) transfer_accounts = response.json['data']['transfer_accounts'] assert response.status_code == 200 user_names = [] for transfer_account in transfer_accounts: if transfer_account['users']: user_names.append(transfer_account['users'][0]['first_name']) assert expected_results[e] == user_names db.session.execute('DROP MATERIALIZED VIEW search_view CASCADE;') db.session.commit()
def test_transfer_card_radius(test_client, init_database, complete_admin_auth_token, authed_sempo_admin_user, create_organisation): from server.utils.user import create_transfer_account_user def create_card(public_serial_number, nfc_serial_number): return test_client.post('/api/v1/transfer_cards/', headers=dict(Authorization=complete_admin_auth_token, Accept='application/json'), data=json.dumps({ 'public_serial_number': public_serial_number, 'nfc_serial_number': nfc_serial_number }), content_type='application/json', follow_redirects=True) create_card(123456, 'ABCD1234F') create_card(111111, 'AAAA1111A') create_card(222222, 'BBBBB111B') create_card(333333, 'CCCCC222C') create_card(444444, 'DDDDD333D') create_card(555555, 'AAAAVVVVV') create_card(666666, 'AAAAVVVVZ') create_card(777777, 'RAAAVVVVZ') create_card(888888, 'SAAAVVVVZ') # Create users user1 = create_transfer_account_user(first_name='Arthur', last_name='Read', phone='+19027191111', organisation=create_organisation) user2 = create_transfer_account_user(first_name='Francine', last_name='Fresnky', phone='+19027192222', organisation=create_organisation) user3 = create_transfer_account_user(first_name='Muffy', last_name='Crosswire', phone='+19027193333', organisation=create_organisation) user4 = create_transfer_account_user(first_name='Buster', last_name='Baxter', phone='+19027194444', organisation=create_organisation) user5 = create_transfer_account_user(first_name='Buster', last_name='Baxter', phone='+19027195555', organisation=create_organisation) user6 = create_transfer_account_user(first_name='Binky', last_name='Barnes', phone='+19027195455', organisation=create_organisation) user7 = create_transfer_account_user(first_name='Nigel', last_name='Ratburn', phone='+19027195415', organisation=create_organisation) user8 = create_transfer_account_user(first_name='DW', last_name='Read', phone='+19027135415', organisation=create_organisation) user9 = create_transfer_account_user(first_name='Kate', last_name='Read', phone='+19027134415', organisation=create_organisation) # Set locations authed_sempo_admin_user.lat = 44.650070 authed_sempo_admin_user.lng = -63.598863 authed_sempo_admin_user.location = 'Halifax' # Base user (Halifax) user1.lat = 44.650069 user1.lng = -63.598865 user1.location = 'Halifax' # Nearby user (Dartmouth) user2.lat = 44.679730 user2.lng = -63.583979 user2.location = 'Dartmouth' # Kinda far user (Wolfville) user3.lat = 45.099418 user3.lng = -64.323369 user3.location = 'Wolfville' # Very far user (Melbourne) user4.lat = -37.874072 user4.lng = 145.053438 user4.location = 'Melbourne' # Null lat/lng. We want to catch these! user5.lat = None user5.lng = None user5.location = None # Incorrect coords, but same location name (Halifax) user6.lat = 10.1 user6.lng = -10.5 user6.location = 'Halifax' # Identical coords to main user user7.lat = 44.650070 user7.lng = -63.598863 user7.location = 'Halifax' # Extremely close coords to main user user8.lat = 44.650071 user8.lng = -63.598864 user8.location = 'Halifax' # Null location user9.lat = None user9.lng = None user9.location = None db.session.commit() # Bind users def bind_user(id, serial_number): test_client.put( f"/api/v1/user/{id}/", headers=dict( Authorization=complete_admin_auth_token, Accept='application/json' ), json={ 'public_serial_number': serial_number }) bind_user(user1.id, 123456) bind_user(user2.id, 111111) bind_user(user3.id, 222222) bind_user(user4.id, 333333) bind_user(user5.id, 444444) bind_user(user6.id, 555555) bind_user(user7.id, 666666) bind_user(user8.id, 777777) bind_user(user9.id, 888888) # Make sure the distance filters are working! distances = [(None, 9), (0, 9), (0.001, 6), (2, 6),(10, 7), (100, 8), (100000, 9)] for distance, length in distances: # Set card shard distance create_organisation.card_shard_distance=distance db.session.commit() # Get it now! response = test_client.get('/api/v1/transfer_cards/', headers=dict( Authorization=complete_admin_auth_token, Accept='application/json'), follow_redirects=True) assert len(response.json['data']['transfer_cards']) == length # Check that the sharding flag works (false) create_organisation.card_shard_distance=1 response = test_client.get('/api/v1/transfer_cards/?shard=false', headers=dict( Authorization=complete_admin_auth_token, Accept='application/json'), follow_redirects=True) assert len(response.json['data']['transfer_cards']) == 9 # Check that the sharding flag works (true) response = test_client.get('/api/v1/transfer_cards/?shard=true', headers=dict( Authorization=complete_admin_auth_token, Accept='application/json'), follow_redirects=True) assert len(response.json['data']['transfer_cards']) == 6 # Check that it doesn't try to shard when the user doesn't have coords authed_sempo_admin_user.lat = None authed_sempo_admin_user.lng = None response = test_client.get('/api/v1/transfer_cards/', headers=dict( Authorization=complete_admin_auth_token, Accept='application/json'), follow_redirects=True) assert len(response.json['data']['transfer_cards']) == 9
def test_transfer_account_history(test_client, authed_sempo_admin_user): user = create_transfer_account_user(first_name='Transfer', last_name='User 2', phone=Faker().msisdn()) db.session.commit() transfer_account = user.default_transfer_account transfer_account.is_approved = True authed_sempo_admin_user.set_held_role('ADMIN', 'superadmin') auth = get_complete_auth_token(authed_sempo_admin_user) def update_account(json, id): test_client.put(f"/api/v1/transfer_account/{id}/", headers=dict(Authorization=auth, Accept='application/json'), json=json) # Update a bunch of stuff update_account( { 'transfer_account_name': 'Sample', 'approve': True, 'notes': 'This account has a comment!' }, transfer_account.id) update_account({'notes': 'This account has a refreshed comment!'}, transfer_account.id) update_account({'approve': False}, transfer_account.id) update_account({'transfer_account_name': 'Sample Account'}, transfer_account.id) result = test_client.get( f"/api/v1/transfer_account/history/{transfer_account.id}/", headers=dict(Authorization=auth, Accept='application/json')) # Zero the dates because they'll change each time the tests are run results = [] for c in result.json['data']['changes']: c['created'] = None c['change_by'] = None results.append(c) assert { 'change_by': None, 'column_name': 'notes', 'created': None, 'new_value': 'This account has a refreshed comment!', 'old_value': 'This account has a comment!' } in results assert { 'change_by': None, 'column_name': 'is_approved', 'created': None, 'new_value': 'False', 'old_value': 'True' } in results assert { 'change_by': None, 'column_name': 'name', 'created': None, 'new_value': 'Sample Account', 'old_value': 'Sample' } in results
def create_transfer_user(email, transfer_usages, organisation, created_offset): first_name, middle_name = random.sample(ADJECTIVES, 2) last_name = f'{middle_name} {random.choice(ANIMALS)}' is_beneficiary = rand_bool(0.9) if is_beneficiary: roles = roles = [('BENEFICIARY', 'beneficiary')] else: roles = [('VENDOR', 'vendor')] phone = '+1' + ''.join([str(random.randint(0, 10)) for i in range(0, 10)]) user = create_transfer_account_user( first_name=first_name, last_name=last_name, email=email, phone=phone, organisation=organisation, roles=roles, ) # Set the created date to the first day user.created = datetime.utcnow() - timedelta(days=created_offset) location, lat, lng = random.choice(LOCATIONS) # Assign the user to a random location and jitter the latlong slightly user._location = location user.lat = lat + random.random() / 100 user.lng = lng + random.random() / 100 attribute_dict = {'custom_attributes': {}} attribute_dict['custom_attributes']['gender'] = random.choice( ['male', 'female']) set_custom_attributes(attribute_dict, user) if not is_beneficiary: bu = random.choice(transfer_usages) user.business_usage = bu # Create purchase behavior profile behavior = {} # 10% chance the user's purchase will always include a particular category single_item_purchaser = rand_bool(0.1) if single_item_purchaser: item = random.choice(transfer_usages) behavior['purchase_item'] = item else: behavior['purchase_item'] = None # A fixed likelihood that this user will actually make a purchase if selected. behavior['spend_probability'] = random.random() # The likelihood that the user's purchase is at a different location behavior['out_of_town_probability'] = random.random() / 3 return user, behavior
def test_prep_search_api(test_client, complete_admin_auth_token, create_organisation): # This is a hack because the test DB isn't being built with migrations (and thus doesn't have trigrams) db.session.execute(''' CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE INDEX trgm_first_name ON "user" USING gist (first_name gist_trgm_ops); CREATE INDEX trgm_last_name ON "user" USING gist (last_name gist_trgm_ops); CREATE INDEX trgm_phone ON "user" USING gist (_phone gist_trgm_ops); CREATE INDEX trgm_public_serial_number ON "user" USING gist (_public_serial_number gist_trgm_ops); CREATE INDEX trgm_primary_blockchain_address ON "user" USING gist (primary_blockchain_address gist_trgm_ops); CREATE INDEX trgm_location ON "user" USING gist (_location gist_trgm_ops); ''') # Adds users we're searching for michiel = create_transfer_account_user(first_name='Michiel', last_name='deRoos', phone='+19025551234', organisation=create_organisation, initial_disbursement = 100) michiel.location = 'Halifax' francine = create_transfer_account_user(first_name='Francine', last_name='deRoos', phone='+19025552345', organisation=create_organisation, initial_disbursement = 200) francine.location = 'Dartmouth' roy = create_transfer_account_user(first_name='Roy', last_name='Donk', phone='+12345678901', organisation=create_organisation, initial_disbursement = 200) roy.location = 'Burbank' paul = create_transfer_account_user(first_name='Paul', last_name='Bufano', phone='+98765432123', organisation=create_organisation, initial_disbursement = 200) paul.location = 'California' db.session.commit() def make_transfer(amount, recipient_user_id, sender_user_id, transfer_type): test_client.post( '/api/v1/credit_transfer/', headers=dict( Authorization=complete_admin_auth_token, Accept='application/json' ), data=json.dumps(dict( transfer_amount=amount, sender_user_id=sender_user_id, recipient_user_id=recipient_user_id, transfer_type=transfer_type, )), content_type='application/json', follow_redirects=True) make_transfer(5, paul.id, michiel.id, 'PAYMENT') make_transfer(2, francine.id, roy.id, 'DISBURSEMENT') make_transfer(6, roy.id, paul.id, 'PAYMENT') make_transfer(23, michiel.id, francine.id, 'PAYMENT') db.session.commit()
def generate_timeseries_metrics(create_organisation): # Generates metrics over timeline # User1 and User2 made today user1 = create_transfer_account_user(first_name='Ricky', phone="+19025551234", organisation=create_organisation, roles=[('BENEFICIARY', 'beneficiary') ]) user1.default_transfer_account.is_approved = True user1.default_transfer_account._make_initial_disbursement(100, True) user1._location = 'Sunnyvale' user2 = create_transfer_account_user(first_name='Bubbles', phone="+19025551235", organisation=create_organisation) user2.default_transfer_account.is_approved = True user2.default_transfer_account._make_initial_disbursement(200, True) user2._location = 'Sunnyvale' # user3 made yesterday user3 = create_transfer_account_user(first_name='Julian', phone="+19025531230", organisation=create_organisation) user3.default_transfer_account.is_approved = True disburse = user3.default_transfer_account._make_initial_disbursement( 210, True) user3.created = user3.created - timedelta(days=1) disburse.created = user3.created - timedelta(days=1) user3._location = 'Dartmouth' # user4 made 4 days ago user4 = create_transfer_account_user(first_name='Randy', phone="+19025511230", organisation=create_organisation) user4.default_transfer_account.is_approved = True disburse = user4.default_transfer_account._make_initial_disbursement( 201, True) user4.created = user4.created - timedelta(days=4) disburse.created = user4.created - timedelta(days=4) user4._location = 'Lower Sackville' # user5/user6 made 10 days ago user5 = create_transfer_account_user(first_name='Cory', phone="+19011531230", organisation=create_organisation) user5.default_transfer_account.is_approved = True disburse = user5.default_transfer_account._make_initial_disbursement( 202, True) user5.created = user5.created - timedelta(days=10) disburse.created = user5.created - timedelta(days=10) user5._location = 'Truro' user6 = create_transfer_account_user(first_name='Trevor', phone="+19025111230", organisation=create_organisation) user6.default_transfer_account.is_approved = True disburse = user6.default_transfer_account._make_initial_disbursement( 204, True) user6.created = user6.created - timedelta(days=10) disburse.created = user6.created - timedelta(days=10) db.session.commit() tu1 = TransferUsage.find_or_create("Pepperoni") tu2 = TransferUsage.find_or_create("Jalepeno Chips") tu3 = TransferUsage.find_or_create("Shopping Carts") tu1.created = tu1.created - timedelta(days=15) tu2.created = tu1.created - timedelta(days=15) tu3.created = tu1.created - timedelta(days=15) p1 = make_payment_transfer( 100, create_organisation.token, send_user=user1, send_transfer_account=user1.default_transfer_account, receive_user=user2, receive_transfer_account=user2.default_transfer_account, transfer_use=str(int(tu1.id))) p2 = make_payment_transfer( 25, create_organisation.token, send_user=user3, send_transfer_account=user3.default_transfer_account, receive_user=user4, receive_transfer_account=user4.default_transfer_account, transfer_use=str(int(tu1.id))) p2.created = p2.created - timedelta(days=1) p3 = make_payment_transfer( 5, create_organisation.token, send_user=user4, send_transfer_account=user4.default_transfer_account, receive_user=user2, receive_transfer_account=user2.default_transfer_account, transfer_use=str(int(tu2.id))) p3.created = p3.created - timedelta(days=1) p4 = make_payment_transfer( 20, create_organisation.token, send_user=user5, send_transfer_account=user5.default_transfer_account, receive_user=user6, receive_transfer_account=user6.default_transfer_account, transfer_use=str(int(tu3.id))) p4.created = p4.created - timedelta(days=4) p4 = make_payment_transfer( 20, create_organisation.token, send_user=user6, send_transfer_account=user6.default_transfer_account, receive_user=user5, receive_transfer_account=user5.default_transfer_account, transfer_use=str(int(tu2.id))) p4.created = p4.created - timedelta(days=6) db.session.commit()