from http import HTTPStatus from unittest.mock import MagicMock, Mock, patch from abacus_common_logic.utils.dates import current_timestamp from flask.testing import FlaskClient import pytest from payee.config import Config from payee.connectors.secure_data.manager import SecureDocumentManager from payee.constants.constants import ACCOUNT_PAYEE_ACTION_NAMES from payee.constants.error import ( ERROR_DONT_HAVE_PERMISSIONS, ERROR_NO_VALID_IDENTITY_IN_CONTEXT, ) from payee.logic.secure_document import save_secure_document_details_by_payee_id from payee.models.account_payee import AccountPayee from payee.models.bank_details import BankDetailsDocument from payee.models.payee import Payee from payee.models.payee_collaborator import PayeeCollaborator from tests.utils.auth import MockJWTAuth from tests.utils.factories import ( AccountPayeeFactory, BankDetailsIndividualTypeFlattenFactory, ) account_payee_id_output = '1' @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_details', return_value=None) @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_create_success( mock_register_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully registering new payee with individual type.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_details', return_value=None) @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_create_failure_email_phone( mock_register_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test failure registering new payee with individual type.""" account_payee = AccountPayeeFactory.build(account_payee_id=1) mock_get_by_id.return_value = account_payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 400, res.text assert res.json['message']['json']['contact'].keys() == { 'email', 'phone_country', 'phone', } @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_details', return_value=None) @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_create_failure_no_phone_required( mock_register_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Account payees must provide phone/phone_country after the FF teardown.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', 'email': 'test@example.com', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 400, res.text assert res.json['message']['json']['contact'].keys() == { 'phone', 'phone_country', } mock_register_payee.assert_not_called() @patch('payee.models.payee.Payee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_details', return_value=None) @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_payee_bank_details_create_success( mock_register_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully registering new payee with individual type.""" payee_id = 1 payee = Payee(payee_id=payee_id, payoneer_client_reference_id='abc') payee_collaborator = PayeeCollaborator(payee_id=payee_id) payee.get_typed_payee = MagicMock(return_value=payee_collaborator) mock_get_by_id.return_value = payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'payoneer_client_reference_id': 'abc'}.items() ) @patch('payee.models.payee.Payee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_details', return_value=None) @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_payee_bank_details_create_success_email_and_phone_required_skip( mock_register_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Generic payee flow skips the email/phone requirement (account-payee only).""" payee_id = 1 payee = Payee(payee_id=payee_id, payoneer_client_reference_id='abc') payee_collaborator = PayeeCollaborator(payee_id=payee_id) payee.get_typed_payee = MagicMock(return_value=payee_collaborator) mock_get_by_id.return_value = payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text @patch('payee.models.payee.Payee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_details', return_value=None) @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_payee_bank_details_create_success_no_phone_backwards_compatible( mock_register_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully registering new payee with individual type.""" payee_id = 1 payee = Payee(payee_id=payee_id, payoneer_client_reference_id='abc') payee_collaborator = PayeeCollaborator(payee_id=payee_id) payee.get_typed_payee = MagicMock(return_value=payee_collaborator) mock_get_by_id.return_value = payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', 'email': 'test@example.com', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text expected_details = {**details, 'payoneer_client_reference_id': 'abc'} expected_details['contact']['phone'] = None expected_details['contact']['phone_country'] = None assert res.json.items() >= expected_details.items() @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_details', return_value=False) @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_company_create_success( mock_register_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully registering new payee with company type.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'contact': { 'email': 'tesr@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_details', return_value=False) @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_company_create_success_no_contact_backwards_compatible( mock_register_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully registering new payee with company type.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value={}) @patch('payee.logic.bank_details.get_payee_details') @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch( 'payee.logic.bank_details.update_payout_methods', return_value='Updated payout methods', ) @patch('payee.logic.bank_details.update_profile', return_value='Updated profile') @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_update_success( mock_register_payee, mock_update_payout_methods, mock_update_profile, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully updating payee.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } mock_get_payee_details.return_value = None res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) mock_get_payee_details.return_value = details new_details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '3452345523452'}, {'name': 'AccountName', 'value': 'John Smith2'}, {'name': 'BankName', 'value': 'Bank of Hope2'}, {'name': 'RoutingNumber', 'value': '1221051552'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=new_details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**new_details, 'account_payee_id': account_payee_id_output}.items() ) @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value={}) @patch('payee.logic.bank_details.get_payee_details') @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch( 'payee.logic.bank_details.update_payout_methods', return_value='Updated payout methods', ) @patch('payee.logic.bank_details.update_profile', return_value='Updated profile') @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_update_failure_no_phone_required( mock_register_payee, mock_update_payout_methods, mock_update_profile, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Account payees must provide phone/phone_country after the FF teardown.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', 'email': 'test@example.com', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } mock_get_payee_details.return_value = None res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 400, res.text assert res.json['message']['json']['contact'].keys() == { 'phone', 'phone_country', } mock_register_payee.assert_not_called() @pytest.mark.parametrize('is_name_changed', (True, False)) @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states') @patch('payee.logic.bank_details.get_payee_details') @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.release_payee') @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_update_changed_name_or_country_success( mock_register_payee, mock_payoneer_release_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, is_name_changed: bool, ): """Test successfully updating payee.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'date_of_birth': '2000-10-10', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } mock_get_payee_details.return_value = None mock_get_account_payee_states.return_value = { 'banking_details_review': {'action_status': 'rejected'} } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) mock_get_payee_details.return_value = details new_details = { 'type': 'INDIVIDUAL', 'contact': { **( {'first_name': 'firstName2', 'last_name': 'lastName2'} if is_name_changed else {'first_name': 'firstName', 'last_name': 'lastName'} ), 'date_of_birth': '2000-10-10', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { **({'country_code': 'US'} if is_name_changed else {'country_code': 'GB'}), 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '3452345523452'}, {'name': 'AccountName', 'value': 'John Smith2'}, {'name': 'BankName', 'value': 'Bank of Hope2'}, {'name': 'RoutingNumber', 'value': '1221051552'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=new_details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**new_details, 'account_payee_id': account_payee_id_output}.items() ) assert mock_register_payee.call_count == 2 mock_payoneer_release_payee.assert_called_once() @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value={}) @patch('payee.logic.bank_details.get_payee_details') @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch( 'payee.logic.bank_details.update_payout_methods', return_value='Updated payout methods', ) @patch('payee.logic.bank_details.update_profile', return_value='Updated profile') @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_update_company_success( mock_register_payee, mock_update_payout_methods, mock_update_profile, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully updating payee.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'contact': { 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } mock_get_payee_details.return_value = None res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) mock_get_payee_details.return_value = details new_details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'contact': { 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '3452345523452'}, {'name': 'AccountName', 'value': 'John Smith2'}, {'name': 'BankName', 'value': 'Bank of Hope2'}, {'name': 'RoutingNumber', 'value': '1221051552'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=new_details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**new_details, 'account_payee_id': account_payee_id_output}.items() ) @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states', return_value={}) @patch('payee.logic.bank_details.get_payee_details') @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch( 'payee.logic.bank_details.update_payout_methods', return_value='Updated payout methods', ) @patch('payee.logic.bank_details.update_profile', return_value='Updated profile') @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_update_company_success_no_contact_backwards_compatible( mock_register_payee, mock_update_payout_methods, mock_update_profile, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully updating payee.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } mock_get_payee_details.return_value = None res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) mock_get_payee_details.return_value = details new_details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '3452345523452'}, {'name': 'AccountName', 'value': 'John Smith2'}, {'name': 'BankName', 'value': 'Bank of Hope2'}, {'name': 'RoutingNumber', 'value': '1221051552'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=new_details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**new_details, 'account_payee_id': account_payee_id_output}.items() ) @patch('payee.models.account_payee.AccountPayee.get_by_id') @patch('payee.logic.bank_details.set_states', return_value=[]) @patch('payee.logic.bank_details.get_payee_states') @patch('payee.logic.bank_details.get_payee_details') @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.release_payee') @patch('payee.logic.bank_details.register_payee', return_value='Added payee') def test_post_bank_details_update_company_changed_name_success( mock_register_payee, mock_payoneer_release_payee, mock_perm, mock_get_payee_details, mock_get_account_payee_states, mock_set_states, mock_get_by_id, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, ): """Test successfully updating payee.""" payee = AccountPayee(account_payee_id=1) account_payee = AccountPayeeFactory.build(account_payee_id=payee.account_payee_id) mock_get_by_id.return_value = account_payee details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } mock_get_payee_details.return_value = None mock_get_account_payee_states.return_value = { 'banking_details_review': {'action_status': 'approved'} } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) mock_get_payee_details.return_value = details new_details = { 'type': 'COMPANY', 'company': {'name': 'asdf 123'}, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '3452345523452'}, {'name': 'AccountName', 'value': 'John Smith2'}, {'name': 'BankName', 'value': 'Bank of Hope2'}, {'name': 'RoutingNumber', 'value': '1221051552'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/sync-whitelabel-profile', json=new_details, headers=mock_bypass_headers, ) assert res.status_code == 201, res.text assert ( res.json.items() >= {**new_details, 'account_payee_id': account_payee_id_output}.items() ) def test_save_payee_bank_details_individual_success( fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_dynamodb_table, mock_config, mock_jwt_auth, ): """Test successfully registering new payee with individual type.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/bank-details', json=details, headers=mock_jwt_auth.headers, ) details['contact']['date_of_birth'] = None assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) new_details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName2', 'last_name': 'lastName2', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'bank_account_type': 'PERSONAL', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '3452345523452'}, {'name': 'AccountName', 'value': 'John Smith2'}, {'name': 'BankName', 'value': 'Bank of Hope2'}, {'name': 'RoutingNumber', 'value': '1221051552'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/bank-details', json=new_details, headers=mock_jwt_auth.headers, ) assert res.status_code == 400 assert ( res.text == '{"code": "error", "message": "Payee bank details already exists"}' ) @patch('payee.logic.secure_document.current_timestamp') def test_save_payee_bank_details_individual_empty_fields_success( mock_current_timestamp: Mock, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_dynamodb_table, mock_config, mock_jwt_auth, ): """Test successfully registering new payee with individual type.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] ts = current_timestamp() mock_current_timestamp.return_value = ts details = { 'address': { 'address_1': '', 'address_2': '', 'city': '', 'country_code': '', 'province': '', 'zip': '', }, 'contact': { 'date_of_birth': '', 'first_name': '', 'last_name': '', 'email': '', 'phone': '', 'phone_country': '', }, 'payout_method': { 'bank_account_type': '', 'bank_field_details': [ {'name': 'AccountNumber', 'value': ''}, {'name': 'AccountName', 'value': 'John Smith'}, ], 'country': '', 'currency': '', }, 'type': 'INDIVIDUAL', } res = fixture_client.post( '/account-payee/1/bank-details', json=details, headers=mock_jwt_auth.headers, ) assert res.status_code == 201, res.text assert res.json == { 'address': { 'address_1': None, 'address_2': '', 'city': None, 'country_code': None, 'province': None, 'zip': None, }, 'contact': { 'date_of_birth': None, 'first_name': None, 'last_name': None, 'email': None, 'phone': None, 'phone_country': None, }, 'payout_method': { 'bank_account_type': None, 'bank_field_details': [ {'name': 'AccountName', 'value': 'John Smith'}, ], 'country': None, 'currency': None, }, 'type': 'INDIVIDUAL', 'account_payee_id': account_payee_id_output, 'payoneer_client_reference_id': '1', 'modified_at': ts.strftime(SecureDocumentManager.date_format), } @patch('payee.logic.secure_document.current_timestamp') def test_save_payee_bank_details_company_empty_fields_success( mock_current_timestamp: Mock, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_dynamodb_table, mock_config, mock_jwt_auth, ): """Test successfully registering new payee with individual type.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] ts = current_timestamp() mock_current_timestamp.return_value = ts details = { 'address': { 'address_1': '', 'address_2': '', 'city': '', 'country_code': '', 'province': '', 'zip': '', }, 'company': {'name': ''}, 'contact': { 'email': '', 'phone': '', 'phone_country': '', }, 'payout_method': { 'bank_account_type': '', 'bank_field_details': [ {'name': 'AccountNumber', 'value': ''}, {'name': 'AccountName', 'value': 'John Smith'}, ], 'country': '', 'currency': '', }, 'type': 'COMPANY', } res = fixture_client.post( '/account-payee/1/bank-details', json=details, headers=mock_jwt_auth.headers, ) assert res.status_code == 201, res.text assert res.json == { 'address': { 'address_1': None, 'address_2': '', 'city': None, 'country_code': None, 'province': None, 'zip': None, }, 'company': {'name': None}, 'contact': {'email': None, 'phone': None, 'phone_country': None}, 'payout_method': { 'bank_account_type': None, 'bank_field_details': [ {'name': 'AccountName', 'value': 'John Smith'}, ], 'country': None, 'currency': None, }, 'type': 'COMPANY', 'account_payee_id': account_payee_id_output, 'payoneer_client_reference_id': '1', 'modified_at': ts.strftime(SecureDocumentManager.date_format), } def test_save_payee_bank_details_individual_success_missing_fields( fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_dynamodb_table, mock_config, mock_jwt_auth, ): """Test successfully registering new payee with individual type.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] details = { 'type': 'INDIVIDUAL', 'contact': { 'first_name': 'firstName', 'last_name': 'lastName', 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', 'zip': '65000', }, 'payout_method': { 'country': 'US', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/bank-details', json=details, headers=mock_jwt_auth.headers, ) details['contact']['date_of_birth'] = None details['payout_method']['currency'] = None details['payout_method']['bank_account_type'] = None assert res.status_code == 201, res.text assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) def test_save_payee_bank_details_company_success( fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_dynamodb_table, mock_config, mock_jwt_auth, ): """Test successfully registering new payee with company type.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'contact': { 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/bank-details', json=details, headers=mock_jwt_auth.headers ) assert res.status_code == 201, res.text details['address']['zip'] = None assert ( res.json.items() >= {**details, 'account_payee_id': account_payee_id_output}.items() ) new_details = { 'type': 'COMPANY', 'company': {'name': 'asdf 123'}, 'contact': { 'email': 'test@example.com', 'phone': '4567890', 'phone_country': 'US', }, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '3452345523452'}, {'name': 'AccountName', 'value': 'John Smith2'}, {'name': 'BankName', 'value': 'Bank of Hope2'}, {'name': 'RoutingNumber', 'value': '1221051552'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( '/account-payee/1/bank-details', json=new_details, headers=mock_jwt_auth.headers ) assert res.status_code == 400 assert ( res.text == '{"code": "error", "message": "Payee bank details already exists"}' ) @patch('payee.utils.permissions.validate_record_owner', return_value=True) def test_purge_payee_bank_details_success( mock_perm, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, mock_config, mock_jwt_auth, ): """Test successful purge of payee bank details.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] payee_id = 1 details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } res = fixture_client.post( f'/account-payee/{payee_id}/bank-details', json=details, headers=mock_jwt_auth.headers, ) assert res.status_code == 201, res.text res = fixture_client.get( f'/account-payee/{payee_id}/bank-details', headers=mock_jwt_auth.headers, ) assert res.status_code == 200, res.text res = fixture_client.delete( f'/account-payee/{payee_id}/bank-details', headers=mock_jwt_auth.headers ) assert res.status_code == 204, res.text # check if can delete again, should return 204 res = fixture_client.delete( f'/account-payee/{payee_id}/bank-details', headers=mock_jwt_auth.headers ) assert res.status_code == 204, res.text res = fixture_client.get( f'/account-payee/{payee_id}/bank-details', headers=mock_bypass_headers, ) assert res.status_code == 404, res.text @patch('payee.utils.validations._get_vendor_ids', return_value=[]) def test_get_payee_bank_details_failure_auth( _, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_dynamodb_table, mock_config, fixture_client, ): result = fixture_client.get(f'/account-payee/1/bank-details') assert result.status_code == 401 assert result.json == { 'error': f'{ERROR_NO_VALID_IDENTITY_IN_CONTEXT}, {ERROR_DONT_HAVE_PERMISSIONS}' } @patch('payee.utils.permissions.validate_record_owner', return_value=True) @patch('payee.logic.bank_details.has_secure_document_details', return_value=None) def test_purge_payee_bank_details_many_snapshots_success( mock_has_secure_document_details, mock_perm, fresh_db, fixture_client, account_fixtures, payoneer_program_fixtures, account_payee_fixtures, mock_bypass_headers, mock_dynamodb_table, mock_config, mock_jwt_auth, ): """Test successful purge of payee bank details.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] payee_id = 1 details = { 'type': 'COMPANY', 'company': {'name': 'asdf'}, 'address': { 'country_code': 'US', 'address_1': 'asdf', 'address_2': 'dfgh', 'city': 'odesa', 'province': 'AZ', }, 'payout_method': { 'bank_account_type': 'COMPANY', 'country': 'US', 'currency': 'USD', 'bank_field_details': [ {'name': 'AccountNumber', 'value': '345234552345'}, {'name': 'AccountName', 'value': 'John Smith'}, {'name': 'BankName', 'value': 'Bank of Hope'}, {'name': 'RoutingNumber', 'value': '122105155'}, {'name': 'AccountType', 'value': 'S'}, ], }, } for _ in range(30): # must be more than 25, due to bulk items update API limit res = fixture_client.post( f'/account-payee/{payee_id}/bank-details', json=details, headers=mock_jwt_auth.headers, ) assert res.status_code == 201, res.text res = fixture_client.get( f'/account-payee/{payee_id}/bank-details', headers=mock_bypass_headers, ) assert res.status_code == 200, res.text res = fixture_client.delete( f'/account-payee/{payee_id}/bank-details', headers=mock_jwt_auth.headers ) assert res.status_code == 204, res.text res = fixture_client.get( f'/account-payee/{payee_id}/bank-details', headers=mock_bypass_headers, ) assert res.status_code == 404, res.text @patch('payee.logic.bank_details.create_payee_states') @patch('payee.logic.bank_details.get_payee_states') @patch('payee.logic.bank_details.register_payee') def test_post_register_whitelabel_profile_success( mock_register_payee: Mock, mock_get_account_payee_states: Mock, mock_create_payee_states: Mock, fresh_db: None, fixture_client: FlaskClient, account_fixtures: None, payoneer_program_fixtures: None, account_payee_fixtures: None, mock_jwt_auth: MockJWTAuth, mock_dynamodb_table: None, ) -> None: """Test successfully registering whitelabel profile with existing bank details.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] account_payee_id = 1 mock_get_account_payee_states.return_value = {} bank_details = BankDetailsIndividualTypeFlattenFactory.build() save_secure_document_details_by_payee_id( account_payee_id, BankDetailsDocument, **bank_details ) res = fixture_client.post( f'/account-payee/{account_payee_id}/register-whitelabel-profile', headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.OK, res.text mock_get_account_payee_states.assert_called_once_with(account_payee_id) mock_register_payee.assert_called_once_with( AccountPayee.get_payee_by_id(1), bank_details | { 'account_payee_id': account_payee_id, 'modified_at': None, 'modified_by_identity': None, 'modified_by_profile_id': None, 'modified_by_profile_type': None, 'name': None, }, ) mock_create_payee_states.assert_called_once_with( account_payee_id, 'account_payee', [ACCOUNT_PAYEE_ACTION_NAMES.BANKING_DETAILS_REVIEW], ) @patch('payee.logic.bank_details.create_payee_states') @patch('payee.logic.bank_details.get_payee_states') @patch('payee.logic.bank_details.register_payee') def test_post_register_whitelabel_profile_failure_no_account( mock_register_payee: Mock, mock_get_account_payee_states: Mock, mock_create_payee_states: Mock, fresh_db: None, fixture_client: FlaskClient, mock_jwt_auth: MockJWTAuth, ) -> None: """Test registering whitelabel profile for non existing account.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] account_payee_id = 1 res = fixture_client.post( f'/account-payee/{account_payee_id}/register-whitelabel-profile', headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.BAD_REQUEST, res.text mock_get_account_payee_states.assert_not_called() mock_register_payee.assert_not_called() mock_create_payee_states.assert_not_called() @patch('payee.logic.bank_details.create_payee_states') @patch('payee.logic.bank_details.get_payee_states') @patch('payee.logic.bank_details.register_payee') def test_post_register_whitelabel_profile_failure_existing_status( mock_register_payee: Mock, mock_get_account_payee_states: Mock, mock_create_payee_states: Mock, fresh_db: None, fixture_client: FlaskClient, account_fixtures: None, payoneer_program_fixtures: None, account_payee_fixtures: None, mock_jwt_auth: MockJWTAuth, mock_dynamodb_table: None, ) -> None: """Test registering whitelabel profile for existing status.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] account_payee_id = 1 mock_get_account_payee_states.return_value = { ACCOUNT_PAYEE_ACTION_NAMES.BANKING_DETAILS_REVIEW: 'abc' } res = fixture_client.post( f'/account-payee/{account_payee_id}/register-whitelabel-profile', headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.UNPROCESSABLE_ENTITY, res.text mock_get_account_payee_states.assert_called_once_with(account_payee_id) mock_register_payee.assert_not_called() mock_create_payee_states.assert_not_called() @patch('payee.logic.bank_details.create_payee_states') @patch('payee.logic.bank_details.get_payee_states') @patch('payee.logic.bank_details.register_payee') def test_post_register_whitelabel_profile_failure_no_banking_details( mock_register_payee: Mock, mock_get_account_payee_states: Mock, mock_create_payee_states: Mock, fresh_db: None, fixture_client: FlaskClient, account_fixtures: None, payoneer_program_fixtures: None, account_payee_fixtures: None, mock_jwt_auth: MockJWTAuth, mock_dynamodb_table: None, ) -> None: """Test registering whitelabel profile for missing banking details.""" mock_jwt_auth.identity = Config.BANK_DETAILS_SERVICE_IDENTITIES[0] account_payee_id = 1 mock_get_account_payee_states.return_value = {} res = fixture_client.post( f'/account-payee/{account_payee_id}/register-whitelabel-profile', headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.UNPROCESSABLE_ENTITY, res.text mock_get_account_payee_states.assert_called_once_with(account_payee_id) mock_register_payee.assert_not_called() mock_create_payee_states.assert_not_called() @patch('payee.logic.bank_details.update_state') @patch('payee.logic.bank_details.get_payee_states') def test_post_reset_banking_states_success( mock_get_payee_states: Mock, mock_update_state: Mock, fresh_db: None, fixture_client: FlaskClient, account_fixtures: None, payoneer_program_fixtures: None, account_payee_fixtures: None, mock_jwt_auth: MockJWTAuth, ) -> None: """Test successfully resetting banking states.""" mock_jwt_auth.identity = Config.PAYONEER_SERVICE_IDENTITIES[0] account_payee_id = 1 mock_get_payee_states.return_value = { ACCOUNT_PAYEE_ACTION_NAMES.BANKING_DETAILS_REVIEW: { 'abacus_state_id': 10, 'action_name': 'banking_details_review', 'action_status': 'approved', 'message': None, }, ACCOUNT_PAYEE_ACTION_NAMES.PAYMENT_ELIGIBILITY: { 'abacus_state_id': 20, 'action_name': 'payment_eligibility', 'action_status': 'approved', 'message': None, }, } res = fixture_client.post( f'/account-payee/{account_payee_id}/reset-banking-states/', headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.OK, res.text mock_get_payee_states.assert_called_once_with(account_payee_id) assert mock_update_state.call_count == 2 @patch('payee.logic.bank_details.update_state') @patch('payee.logic.bank_details.get_payee_states') def test_post_reset_banking_states_no_states( mock_get_payee_states: Mock, mock_update_state: Mock, fresh_db: None, fixture_client: FlaskClient, account_fixtures: None, payoneer_program_fixtures: None, account_payee_fixtures: None, mock_jwt_auth: MockJWTAuth, ) -> None: """Test resetting banking states when no states exist (no-op).""" mock_jwt_auth.identity = Config.PAYONEER_SERVICE_IDENTITIES[0] account_payee_id = 1 mock_get_payee_states.return_value = {} res = fixture_client.post( f'/account-payee/{account_payee_id}/reset-banking-states/', headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.OK, res.text mock_get_payee_states.assert_called_once_with(account_payee_id) mock_update_state.assert_not_called()