Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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
Beispiel #5
0
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()
Beispiel #6
0
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;")
Beispiel #8
0
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
Beispiel #9
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()
Beispiel #10
0
    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
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
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()
Beispiel #16
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.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()