"""Functional tests for payee.""" from unittest.mock import ANY, Mock, patch from payee.constants.constants import ACTION_STATUSES, PAYEE_ACTION_NAMES, PAYEE_TYPES from tests.utils.factories import PayeeFactory @patch('payee.connectors.ows_collaborator.ows_client') @patch('payee.logic.payee.create_payee_states_by_parent_table') def test_create_payee_collaborator( create_payee_states_by_parent_table_mock, mocked_ows_client, fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, fixture_client, ): """Test create payee.""" collaborator_id = 1 mocked_ows_client.get.return_value = Mock( status_code=200, json=Mock( return_value={ 'vendor_id': 1, 'name': 'test', } ), ) res = fixture_client.post( f'/payee-collaborator', json={ 'collaborator_id': collaborator_id, 'reference_payment_type_id': 8, }, ) res_data = res.json assert res.status_code == 201 assert res_data == { 'created_at': ANY, 'created_by': 'default_user_id', 'last_modified': ANY, 'last_modified_by': 'default_user_id', 'payee_id': 1, 'payee_name': 'test', 'payee_type': 'collaborator', 'payoneer_assigned_id': None, 'payoneer_client_reference_id': ANY, 'payoneer_program_id': 1, 'reference_payment_type_id': 8, } @patch('payee.connectors.ows_collaborator.ows_client') @patch('payee.logic.payee.create_payee_states_by_parent_table') def test_create_payee_collaborator_if_exists( create_payee_states_by_parent_table_mock, mocked_ows_client, fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, fixture_client, ): """Test get payee if exists on create.""" collaborator_id = 1 mocked_ows_client.get.return_value = Mock( status_code=200, json=Mock( return_value={ 'vendor_id': 1, 'name': 'test', } ), ) res = fixture_client.post( f'/payee-collaborator', json={ 'collaborator_id': collaborator_id, 'reference_payment_type_id': 8, }, ) res_data = res.json assert res.status_code == 200 assert res_data == { 'created_at': ANY, 'created_by': '', 'last_modified': ANY, 'last_modified_by': '', 'payee_id': 1, 'payee_name': None, 'payee_type': 'collaborator', 'payoneer_assigned_id': None, 'payoneer_client_reference_id': ANY, 'payoneer_program_id': 1, 'reference_payment_type_id': 8, } @patch('payee.connectors.ows_collaborator.ows_client') @patch('payee.logic.payee.create_payee_states_by_parent_table') def test_create_payee_collaborator_if_null_program_id( create_payee_states_by_parent_table_mock, mocked_ows_client, fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, fixture_client, ): """Test create payee fails if program ID is null.""" collaborator_id = 1 mocked_ows_client.get.return_value = Mock( status_code=200, json=Mock( return_value={ 'vendor_id': 6, 'name': 'test', } ), ) res = fixture_client.post( f'/payee-collaborator', json={ 'collaborator_id': collaborator_id, 'reference_payment_type_id': 8, }, ) assert res.status_code == 500 def test_get_payee_dataloader( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, fixture_client, ): """Test get payees.""" res = fixture_client.post('/payee/dataloader', json={'collaborator_ids': [1]}) assert res.status_code == 200 assert res.json == { 'payees': [ { 'data': { 'created_at': ANY, 'created_by': '', 'last_modified': ANY, 'last_modified_by': '', 'payee_id': 1, 'payee_name': ANY, 'payee_type': PAYEE_TYPES.COLLABORATOR, 'payoneer_assigned_id': ANY, 'payoneer_client_reference_id': '1', 'payoneer_program_id': 1, 'reference_payment_type_id': 8, } } ] } def test_get_payee_bulk( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, fixture_client, ): """Test get payees with no filters.""" body = { 'limit': 1, 'offset': 0, } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json == { 'total_count': 2, 'items': [ { 'created_at': ANY, 'created_by': '', 'last_modified': ANY, 'last_modified_by': '', 'payee_id': 1, 'payee_name': ANY, 'payee_type': PAYEE_TYPES.COLLABORATOR, 'payoneer_assigned_id': ANY, 'payoneer_client_reference_id': '1', 'payoneer_program_id': 1, 'reference_payment_type_id': 8, } ], } def test_get_payee_bulk_filter_requires_review( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, abacus_state_fixtures, fixture_client, ): """Test get payees filtered by requires_review (KYC notification state).""" PayeeFactory.create( payee_id=3, reference_payment_type_id=8, payoneer_client_reference_id=3, payoneer_program_id=1, payee_type=PAYEE_TYPES.COLLABORATOR, ) body = { 'limit': 10, 'offset': 0, 'requires_review': True, } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 # Only payee_id=3 has the KYC notification state assert res.json['total_count'] == 1 assert len(res.json['items']) == 1 assert res.json['items'][0]['payee_id'] == 3 def test_get_payee_bulk_filter_abacus_states( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, abacus_state_fixtures, fixture_client, ): """Test get payees filtered by abacus_states.""" # Filter by single state body = { 'limit': 10, 'offset': 0, 'abacus_states': [ { 'action_status': ACTION_STATUSES.COMPLETE, 'action_name': PAYEE_ACTION_NAMES.BANKING_ELIGIBILITY, } ], } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 1 assert res.json['items'][0]['payee_id'] == 1 # Filter by multiple states (OR condition) body['abacus_states'] = [ { 'action_status': ACTION_STATUSES.COMPLETE, 'action_name': PAYEE_ACTION_NAMES.BANKING_ELIGIBILITY, }, { 'action_status': ACTION_STATUSES.ERROR, 'action_name': PAYEE_ACTION_NAMES.BANKING_ELIGIBILITY, }, ] res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 2 assert {p['payee_id'] for p in res.json['items']} == {1, 2} # Filter by action_status only body['abacus_states'] = [{'action_status': ACTION_STATUSES.ERROR}] res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 1 assert res.json['items'][0]['payee_id'] == 2 def test_get_payee_bulk_filter_account_ids( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, fixture_client, ): """Test get payees filtered by account_ids.""" body = { 'limit': 10, 'offset': 0, 'account_ids': [1], } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 # Both payees in fixtures have account_id=1 via collaborator assert res.json['total_count'] == 2 # Filter by non-existent account body['account_ids'] = [999] res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 0 def test_get_payee_bulk_filter_payoneer_program_ids( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, fixture_client, ): """Test get payees filtered by payoneer_program_ids.""" body = { 'limit': 10, 'offset': 0, 'payoneer_program_ids': [1], } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 2 assert all(p['payoneer_program_id'] == 1 for p in res.json['items']) # Filter by non-existent program body['payoneer_program_ids'] = [999] res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 0 def test_get_payee_bulk_filter_search_term_by_name( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, fixture_client, ): """Test get payees filtered by search_term matching payee_name.""" # Create payees with distinct names PayeeFactory.create( payee_id=None, payee_name='Alice Smith', payoneer_client_reference_id='alice-ref', ) PayeeFactory.create( payee_id=None, payee_name='Bob Johnson', payoneer_client_reference_id='bob-ref', ) body = { 'limit': 10, 'offset': 0, 'search_term': 'alice', } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 1 assert res.json['items'][0]['payee_name'] == 'Alice Smith' # Case-insensitive search body['search_term'] = 'ALICE' res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 1 # Partial match body['search_term'] = 'john' res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 1 assert res.json['items'][0]['payee_name'] == 'Bob Johnson' def test_get_payee_bulk_filter_search_term_by_id( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, fixture_client, ): """Test get payees filtered by search_term matching payee_id.""" body = { 'limit': 10, 'offset': 0, 'search_term': '1', } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 1 assert res.json['items'][0]['payee_id'] == 1 # Search for non-existent ID body['search_term'] = '999' res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 0 def test_get_payee_bulk_filter_combined( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, abacus_state_fixtures_complete, fixture_client, ): """Test get payees with multiple filters combined.""" # Create more test data PayeeFactory.create( payee_id=None, payee_name='Charlie Brown', payoneer_client_reference_id='charlie-ref', payoneer_program_id=1, ) # Combine abacus_states and payoneer_program_ids filters body = { 'limit': 10, 'offset': 0, 'abacus_states': [{'action_status': ACTION_STATUSES.COMPLETE}], 'payoneer_program_ids': [1], } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 2 # payee_id 1 and 3 have both conditions assert {p['payee_id'] for p in res.json['items']} == {1, 3} # Combine with search_term filter body['search_term'] = 'Charlie' res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 1 assert res.json['items'][0]['payee_id'] == 3 def test_get_payee_bulk_pagination_with_filters( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, fixture_client, ): """Test pagination works correctly with filters applied.""" # Create multiple payees with the same program for i in range(5): PayeeFactory.create( payee_id=None, payee_name=f'Payee {i}', payoneer_client_reference_id=f'payee-{i}-ref', payoneer_program_id=1, ) body = { 'limit': 2, 'offset': 0, 'payoneer_program_ids': [1], } res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 7 # 2 original + 5 new assert len(res.json['items']) == 2 # Get next page body['offset'] = 2 res = fixture_client.post('/payees/bulk', json=body) assert res.status_code == 200 assert res.json['total_count'] == 7 assert len(res.json['items']) == 2 def test_get_payee_collaborators_bulk( fresh_db, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, payee_fixtures, payee_collaborator_fixtures, fixture_client, ): """Test get payee collaborators.""" body = { 'limit': 1, 'offset': 0, 'payee_ids': [], } res = fixture_client.post('/payee-collaborators/bulk', json=body) assert res.status_code == 200 assert res.json == { 'total_count': 2, 'items': [ { 'created_at': ANY, 'created_by': '', 'last_modified': ANY, 'last_modified_by': '', 'payee_collaborator_id': 1, 'collaborator_id': 1, 'payee_id': 1, 'account_id': 1, } ], }