"""Tests for tax details handlers.""" from typing import Any, Type from unittest.mock import call, MagicMock, Mock, patch from flask import Response from flask.testing import FlaskClient import jwt from marshmallow import ValidationError import pytest import requests from payee.blueprints.tax_details import validate_payoneer_account_id from payee.config import Config from payee.constants.constants import PAYMENT_ENTITIES from payee.constants.error import ( ERROR_DONT_HAVE_PERMISSIONS, ERROR_HMRC_API_UNREACHABLE, ERROR_SESSION_ID_REQUIRED, ) from payee.models.knr_details import KnrDetailsDocument from payee.models.tax_details import TaxDetailsDocument from payee.utils.format_data import flatten_input_data, get_now_timestamp from tests.utils.auth import MockJWTAuth wrong_vat_number_format = 'GBB821018768' wrong_country_code = 'asd' ua_alpha2 = 'UA' ua_alpha3 = 'UKR' us_alpha2 = 'US' us_alpha3 = 'USA' redirect_uri_value = 'AWAL' ts_now = get_now_timestamp() account_id = 1 account_payee_id = 123 @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) @patch('payee.blueprints.tax_details.create_tax_details') @patch('payee.connectors.uk_gov.validate_vat_number', return_value=True) def test_create_tax_details_success( mock_validate_vat_number, mock_logic, mock_corp_entity, fixture_client, mock_payee_vat_registered_tax_details, mock_config, mock_headers, mocker, ): """Test successful creation of new tax details for a payee.""" post_body = mock_payee_vat_registered_tax_details mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) create_params = {**post_body, 'account_payee_id': account_payee_id} flatten_input_data(create_params) # logic returns a simple value mock_logic.return_value = 'ok' res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_body, headers=mock_headers, ) # blueprint endpoint returns a Response assert isinstance(res, Response) assert res.status_code == 201 mock_logic.assert_called_once_with( mock_config.SDM_CONFIG, **create_params, ) @patch('payee.logic.payoneer.get_account_id_by_account_payee_id', return_value=None) @patch('payee.blueprints.tax_details.validate_multiple_record_owner') def test_create_tax_details_failure_corp_entity_account( mock_validate_multiple_record_owner: Mock, _, fixture_client: FlaskClient, mock_headers: dict[str, str], ): """Test failure on tax details creating when getting account ID.""" mock_validate_multiple_record_owner.return_value = ({account_payee_id: True},) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json={}, headers=mock_headers, ) # blueprint endpoint returns a Response assert isinstance(res, Response) assert res.status_code == 400 assert res.json == { 'code': 'error', 'message': { 'error': f'Account_id not found for account_payee_id `{account_payee_id}`' }, } @patch('payee.blueprints.tax_details.get_payee_corp_entity', return_value='XYZ') @patch('payee.blueprints.tax_details.create_tax_details') def test_create_tax_details_error_corp_entity( mock_logic, mock_corp_entity, fixture_client, mock_payee_vat_registered_tax_details, mock_config, mock_headers, mocker, ): """Test failure on creation of new tax details for a payee.""" post_body = mock_payee_vat_registered_tax_details mocker.patch( 'payee.blueprints.tax_details.validate_multiple_record_owner', return_value={account_payee_id: True}, ) create_params = {**post_body, 'account_payee_id': account_payee_id} flatten_input_data(create_params) # logic returns a simple value mock_logic.return_value = 'ok' res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_body, headers=mock_headers, ) # blueprint endpoint returns a Response assert isinstance(res, Response) assert res.status_code == 400 assert res.json == { 'code': 'error', 'message': 'User is not signed to valid corporate entity: "XYZ"', } @patch( 'payee.connectors.uk_gov.get_hmrc_token', return_value='token1', ) @patch('payee.connectors.uk_gov.requests.get') @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) def test_create_tax_details_error_on_uk_vat_timeout( mock_corp_entity: Mock, mock_get: Mock, mock_get_hmrc_token: Mock, fixture_client: FlaskClient, mock_payee_vat_registered_tax_details: dict[str, Any], mock_config: Type[Config], mock_headers: dict[str, str], ): """Test successful creation of new tax details for a payee.""" post_body = dict(mock_payee_vat_registered_tax_details) post_body.pop( 'address' ) # check that HMRC check won't fail because of missing address mock_get.side_effect = requests.exceptions.ConnectTimeout( ERROR_HMRC_API_UNREACHABLE ) create_params = {**post_body, 'account_payee_id': account_payee_id} flatten_input_data(create_params) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_body, headers=mock_headers, ) # blueprint endpoint returns a Response assert isinstance(res, Response) assert res.status_code == 400 assert res.json == {'code': 'error', 'message': {'vat_number': ['API_UNREACHABLE']}} @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) @patch('payee.blueprints.tax_details.create_tax_details') @patch('payee.connectors.uk_gov.validate_vat_number', return_value=True) def test_create_tax_details_error_owner_validation( mock_validate_vat_number, mock_logic, mock_corp_entity, fixture_client, mock_payee_vat_registered_tax_details, mock_config, mocker, ): """Test error on owner validation.""" post_body = mock_payee_vat_registered_tax_details # logic returns a simple value mock_logic.return_value = 'ok' mocker.patch( 'payee.blueprints.tax_details.validate_multiple_record_owner', return_value={account_payee_id: False}, ) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_body ) # blueprint endpoint returns a Response assert isinstance(res, Response) assert res.status_code == 401 @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) def test_create_payment_details_failure(mock_corp_entity, fixture_client): """Test failure to create a new tax details for a payee.""" post_body = {'account_payee_id': account_payee_id} res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_body ) assert res.status_code == 400 @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) @patch('payee.blueprints.tax_details.create_tax_details') def test_create_payment_details_failure_wrong_vat_format( mock_logic, mock_corp_entity, fixture_client, mock_payee_vat_registered_tax_details, mock_config, ): """ Test failure to create a new tax info for a payee. Wrong vat format """ mock_payee_vat_registered_tax_details['vat_number'] = wrong_vat_number_format post_body = mock_payee_vat_registered_tax_details # logic returns a simple value mock_logic.return_value = 'ok' res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_body ) assert res.status_code == 400 @patch('payee.blueprints.tax_details.generate_pdf') @patch('payee.blueprints.tax_details.validate_multiple_record_owner') @patch('payee.blueprints.tax_details.get_tax_receipt_details') def test_generate_receipt_success( mock_logic, mock_validate_record_owner, mock_generate_pdf, fixture_client, mock_payee_vat_registered_tax_details, mock_config, mocker, ): """Test successful generation of a PDF with the tax info.""" pdf_bytes = b'Some bytes' mock_logic_return = { 'account_payee_id': 22, 'vat_registered': True, 'vat_number': 123, 'country_of_tax_residency': 'UK', 'country': 'UK', 'address': 'A very nice address', 'city': 'London', 'state_province_region': None, 'postal_code': None, 'account_name': None, 'signing_entity_name': None, 'signing_entity_vat_number': None, } mock_logic.return_value = mock_logic_return mock_generate_pdf.return_value = pdf_bytes res = fixture_client.get(f'/account-payee/{account_payee_id}/tax-details/receipt') assert res.status_code == 200 assert res.content_type == 'application/pdf' assert res.content_length == len(pdf_bytes) assert res.data == pdf_bytes args, _ = mock_validate_record_owner.call_args assert len(args) == 1 assert args[0] == [account_payee_id] mock_logic.assert_called() mock_generate_pdf.assert_called_once_with(mock_logic_return) @patch('payee.blueprints.tax_details.datetime.datetime') @patch('payee.blueprints.tax_details.get_s3_url_for_file') @patch('payee.blueprints.tax_details.generate_pdf') @patch('payee.blueprints.tax_details.validate_multiple_record_owner') @patch('payee.blueprints.tax_details.get_tax_receipt_details') def test_generate_receipt_url_success( mock_logic, mock_validate_record_owner, mock_generate_pdf, mock_get_s3_url_for_file, mock_datetime, fixture_client, mock_payee_vat_registered_tax_details, mock_config, mock_datetime_object, mocker, ): """Test successful generation of a PDF with the tax info and the S3 URL.""" pdf_bytes = b'Some bytes' mock_logic_return = { 'account_payee_id': 22, 'vat_registered': True, 'vat_number': 123, 'country_of_tax_residency': 'UK', 'country': 'UK', 'address': 'A very nice address', 'city': 'London', 'state_province_region': None, 'postal_code': None, 'account_name': None, 'signing_entity_name': None, 'signing_entity_vat_number': None, } mock_s3_url = 'https://aws.s3.presigned.url.example.com' mock_logic.return_value = mock_logic_return mock_generate_pdf.return_value = pdf_bytes mock_get_s3_url_for_file.return_value = mock_s3_url mock_datetime.utcnow.return_value = mock_datetime_object res = fixture_client.get( f'/account-payee/{account_payee_id}/tax-details/receipt-url' ) assert res.status_code == 200 assert res.json == {'receipt_url': mock_s3_url} args, _ = mock_validate_record_owner.call_args assert len(args) == 1 assert args[0] == [account_payee_id] mock_logic.assert_called() mock_generate_pdf.assert_called_once_with(mock_logic_return) mock_get_s3_url_for_file.assert_called_once_with( pdf_bytes, '2022-05-04_12-16-57_474487.pdf', f'pdf_files/account_payee_id-{account_payee_id}', ) @patch('payee.blueprints.tax_details.generate_payee_payoneer_session_id') @patch( 'payee.blueprints.tax_details.validate_multiple_record_owner', return_value={account_payee_id: True}, ) def test_validate_session_id_success_valid( mock_validate_owner, mock_generate_session_id, mock_config, fixture_client ): """Test validate payoneer session id success.""" session_id = 'session_id' mock_generate_session_id.return_value = session_id res = fixture_client.get( f'/account-payee/{account_payee_id}/validate-session-id?session_id={session_id}' ) assert isinstance(res, Response) assert res.status_code == 200 assert res.json == {'session_id_is_valid': True} @patch( 'payee.blueprints.tax_details.validate_multiple_record_owner', return_value={account_payee_id: True}, ) def test_validate_session_id_empty_session_id_error( mock_validate_owner, mock_config, fixture_client ): """Test validate payoneer session id success.""" session_id = '' res = fixture_client.get( f'/account-payee/{account_payee_id}/validate-session-id?session_id={session_id}' ) assert isinstance(res, Response) assert res.status_code == 400 assert res.json == {'error': ERROR_SESSION_ID_REQUIRED} @patch('payee.blueprints.tax_details.get_payoneer_account') def test_validate_payoneer_account_id_success(mock_payoneer_account): """Test validate account_id success.""" payoneer_account_id = 321 payoneer_token = jwt.encode({'account_id': payoneer_account_id}, 'secret') mock_payoneer_account.return_value = MagicMock( status=200, message={'result': {'account_id': payoneer_account_id}} ) response_account_id = validate_payoneer_account_id(payoneer_token, account_payee_id) assert payoneer_account_id == response_account_id @patch('payee.blueprints.tax_details.get_payoneer_account') def test_validate_payoneer_account_id_error_account(mock_payoneer_account): """Test validate account_id success.""" payoneer_account_id = 321 payoneer_token = jwt.encode({'account_id': account_payee_id}, 'secret') mock_payoneer_account.return_value = MagicMock( status=200, message={'result': {'account_id': payoneer_account_id}} ) is_valid = validate_payoneer_account_id(payoneer_token, account_payee_id) assert not is_valid @patch('payee.blueprints.tax_details.get_tax_details') @patch( 'payee.blueprints.tax_details.validate_multiple_record_owner', return_value={account_payee_id: True}, ) def test_get_payee_tax_details_history( mock_validate_record_owner, mock_documents, fixture_client ): """Test getting tax details history.""" mock_tax_details_1 = { 'vat_number': 'GB821018768', 'country_of_tax_residency_code': 'USA', 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', 'business_name': 'business_name', 'business_number': 'business_number', 'modified_at': '111', 'revision': 'tax_details#XXXXXXXX', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } mock_tax_details_2 = { 'vat_number': 'GB821018768', 'country_of_tax_residency_code': 'BRA', 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', 'business_name': 'business_name', 'business_number': 'business_number', 'modified_at': '222', 'revision': 'tax_details#YYYYYYYYY', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } mock_documents.return_value = ( {}, [ TaxDetailsDocument(mock_tax_details_1), TaxDetailsDocument(mock_tax_details_2), ], ) res = fixture_client.get(f'/account-payee/{account_payee_id}/tax-details-history') assert res.status_code == 200 assert res.json == { 'items': [ { 'account_payee_id': account_payee_id, 'revision': 'XXXXXXXX', }, { 'account_payee_id': account_payee_id, 'revision': 'YYYYYYYYY', }, ] } @patch('payee.blueprints.tax_details.get_secure_document_details') @patch( 'payee.blueprints.tax_details.validate_multiple_record_owner', return_value={account_payee_id: True}, ) def test_get_payee_knr_details_history( mock_validate_record_owner, mock_documents, fixture_client ): """Test getting knr details history.""" mock_knr_details_1 = { 'w_form_expiry': '111', 'w_form_type': 'W8', 'sap_vendor_id': '123', 'revision': 'knr_details#XXXXXXXX', 'modified_at': '111', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } mock_knr_details_2 = { 'w_form_expiry': '222', 'w_form_type': 'W9', 'sap_vendor_id': '123', 'modified_at': '222', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', 'revision': 'knr_details#YYYYYYYYY', } mock_documents.return_value = ( {}, [ KnrDetailsDocument(mock_knr_details_1), KnrDetailsDocument(mock_knr_details_2), ], ) res = fixture_client.get(f'/account-payee/{account_payee_id}/knr-details-history') assert res.status_code == 200 assert res.json == { 'items': [ { 'account_payee_id': account_payee_id, 'revision': 'XXXXXXXX', }, { 'account_payee_id': account_payee_id, 'revision': 'YYYYYYYYY', }, ] } @pytest.mark.parametrize( 'post_body', [ [{'accountPayee': 10, 'revision': None}], [{'accountPayeeId': 11, 'rrr': 'XXX'}], [{}], ], ) def test_get_payee_dataload_tax_details_request_validation_error( post_body, fixture_client, mock_headers ): """Test getting knr details history.""" res = fixture_client.post( '/account-payee/tax-details-dataloader', json=post_body, headers=mock_headers ) assert res.status_code == 404 @patch('payee.logic.secure_document.get_secure_document_revision') @patch('payee.utils.permissions.validate_record_owner', return_value=True) def test_get_payee_dataload_tax_details( mock_perm, mock_doc_revision, fixture_client, mock_bypass_headers ): """Test dataload tax details.""" mock_doc_revision.side_effect = [ None, TaxDetailsDocument( { 'vat_number': 'XXX', 'business_name': 'business_name', 'business_number': None, 'country_of_tax_residency_code': None, 'country_code': 'ITA', 'address_1': 'add', 'address_2': 'add', 'city': 'city', 'province': 'pr', 'zip': '123123', 'revision': 'tax_details#XXX', 'modified_at': 'modified_at', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } ), TaxDetailsDocument( { 'vat_number': 'WWW', 'business_name': 'business_name', 'business_number': None, 'country_of_tax_residency_code': None, 'country_code': 'ITA', 'address_1': 'add', 'address_2': 'add', 'city': 'city', 'province': 'pr', 'zip': '123123', 'revision': 'tax_details#0', 'modified_at': 'modified_at', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } ), ] post_body = [ {'accountPayeeId': 9, 'revision': None}, {'accountPayeeId': 10, 'revision': None}, {'accountPayeeId': 11, 'revision': 'XXX'}, ] res = fixture_client.post( '/account-payee/tax-details-dataloader', json=post_body, headers=mock_bypass_headers, ) assert res.status_code == 200 assert res.json == [ {'data': None}, { 'data': { 'account_payee_id': 10, 'vat_number': 'XXX', 'business_name': 'business_name', 'business_number': None, 'country_of_tax_residency_code': None, 'local_tax_id': None, 'address': { 'country_code': 'ITA', 'address_1': 'add', 'address_2': 'add', 'city': 'city', 'province': 'pr', 'zip': '123123', }, 'revision': 'XXX', 'modified_by': None, 'modified_at': 'modified_at', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } }, { 'data': { 'account_payee_id': 11, 'vat_number': 'WWW', 'business_name': 'business_name', 'business_number': None, 'country_of_tax_residency_code': None, 'local_tax_id': None, 'address': { 'country_code': 'ITA', 'address_1': 'add', 'address_2': 'add', 'city': 'city', 'province': 'pr', 'zip': '123123', }, 'revision': '0', 'modified_at': 'modified_at', 'modified_by': None, 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } }, ] @patch('payee.logic.secure_document.get_secure_document_revision') def test_get_payee_dataload_tax_details_obscure_pii( mock_doc_revision, fixture_client, mock_headers ): """Test dataload tax details.""" mock_doc_revision.side_effect = [ None, TaxDetailsDocument( { 'vat_number': 'XXX', 'business_name': 'business_name', 'business_number': None, 'country_of_tax_residency_code': None, 'country_code': 'ITA', 'address_1': 'add', 'address_2': 'add', 'city': 'city', 'province': 'pr', 'zip': '123123', 'revision': 'tax_details#XXX', 'modified_at': 'modified_at', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } ), TaxDetailsDocument( { 'vat_number': 'WWW', 'business_name': 'business_name', 'business_number': None, 'country_of_tax_residency_code': None, 'country_code': 'ITA', 'address_1': 'add', 'address_2': 'add', 'city': 'city', 'province': 'pr', 'zip': '123123', 'revision': 'tax_details#0', 'modified_at': 'modified_at', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } ), ] post_body = [ {'accountPayeeId': 9, 'revision': None}, {'accountPayeeId': 10, 'revision': None}, {'accountPayeeId': 11, 'revision': 'XXX'}, ] res = fixture_client.post( '/account-payee/tax-details-dataloader', json=post_body, headers=mock_headers, ) assert res.status_code == 200 assert res.json == [ {'data': None}, { 'data': { 'account_payee_id': 10, 'vat_number': None, 'business_name': 'business_name', 'business_number': None, 'country_of_tax_residency_code': None, 'local_tax_id': None, 'address': { 'country_code': 'ITA', 'address_1': 'add', 'address_2': 'add', 'city': 'city', 'province': 'pr', 'zip': '123123', }, 'revision': 'XXX', 'modified_by': None, 'modified_at': 'modified_at', 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } }, { 'data': { 'account_payee_id': 11, 'vat_number': None, 'business_name': 'business_name', 'business_number': None, 'country_of_tax_residency_code': None, 'local_tax_id': None, 'address': { 'country_code': 'ITA', 'address_1': 'add', 'address_2': 'add', 'city': 'city', 'province': 'pr', 'zip': '123123', }, 'revision': '0', 'modified_at': 'modified_at', 'modified_by': None, 'modified_by_identity': 'modified_by_identity', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', } }, ] @patch('payee.logic.secure_document.get_secure_document_revision') @patch( 'payee.blueprints.tax_details.validate_multiple_record_owner', return_value={9: True, 10: True, 11: False}, ) def test_get_payee_dataload_knr_details( mock_validate_record_owner, mock_doc_revision, fixture_client, mock_headers ): """Test dataload knr details.""" mock_doc_revision.side_effect = [ None, KnrDetailsDocument( { 'sap_vendor_id': 321, 'w_form_expiry': 'w_form_expiry', 'w_form_type': 'w_form_type', 'revision': 'knr_details#0', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', 'modified_by_identity': 'modified_by_identity', 'modified_at': 'modified_at', } ), KnrDetailsDocument( { 'sap_vendor_id': 321, 'w_form_expiry': 'w_form_expiry', 'w_form_type': 'w_form_type', 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', 'modified_by_identity': 'modified_by_identity', 'revision': 'knr_details#YYY', 'modified_by': 'modified_by', 'modified_at': 'modified_at', } ), ] post_body = [ {'accountPayeeId': 9, 'revision': None}, {'accountPayeeId': 10, 'revision': None}, {'accountPayeeId': 10, 'revision': 'YYY'}, {'accountPayeeId': 11, 'revision': 'XXX'}, ] res = fixture_client.post( '/account-payee/knr-details-dataloader', json=post_body, headers=mock_headers ) assert res.status_code == 200 assert res.json == [ {'data': None}, { 'data': { 'account_payee_id': 10, 'sap_vendor_id': '321', 'w_form': { 'w_form_expiry': 'w_form_expiry', 'w_form_type': 'w_form_type', }, 'revision': '0', 'modified_by': None, 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', 'modified_by_identity': 'modified_by_identity', 'modified_at': 'modified_at', } }, { 'data': { 'account_payee_id': 10, 'sap_vendor_id': '321', 'w_form': { 'w_form_expiry': 'w_form_expiry', 'w_form_type': 'w_form_type', }, 'revision': 'YYY', 'modified_by': None, 'modified_by_profile_id': 'modified_by_profile_id', 'modified_by_profile_type': 'modified_by_profile_type', 'modified_by_identity': 'modified_by_identity', 'modified_at': 'modified_at', } }, {'error': "You don't have access to this resource!"}, ] @patch('payee.blueprints.tax_details.resync_payment_readiness') def test_resync_payment_readiness_by_account_payee_id_success( mock_logic, fixture_client, mock_headers, mocker ): """Test resync payment readiness.""" mock_logic.return_value = {'account_payee_id': account_payee_id} res = fixture_client.post( f'/account-payee/{account_payee_id}/resync-payment-readiness', headers=mock_headers, ) assert res.status_code == 201 assert res.json == {'account_payee_id': account_payee_id} @patch('payee.blueprints.tax_details.TaxDetailsDocument') @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.blueprints.tax_details.get_tax_details_schema_for_corp_entity') @patch('payee.blueprints.tax_details.has_tax_details') def test_validate_tax_details_success( mock_has_tax_details, mock_get_tax_details_schema_for_corp_entity, mock_get_payee_corp_entity, mock_document, fixture_client, faker, mock_jwt_auth: MockJWTAuth, ): """Test validate tax details success.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] test_corp_entity = faker.pystr() test_account_payee_id = faker.pyint() mock_get_payee_corp_entity.return_value = test_corp_entity mock_get_tax_details_schema_for_corp_entity.return_value.return_value.reverse_validate.return_value = {} res = fixture_client.get( f'/account-payee/{test_account_payee_id}/tax-details/validate', headers=mock_jwt_auth.headers, ) assert res.status_code == 200, res.text assert mock_has_tax_details.call_args_list == [call(test_account_payee_id)] assert mock_get_payee_corp_entity.call_args_list == [call(test_account_payee_id)] assert mock_get_tax_details_schema_for_corp_entity.call_args_list == [ call(test_corp_entity) ] assert mock_document.build_response.call_args_list == [ call(test_account_payee_id, mock_has_tax_details.return_value) ] assert ( mock_get_tax_details_schema_for_corp_entity.return_value.return_value.reverse_validate.call_args_list == [call(mock_document.build_response.return_value)] ) @patch('payee.blueprints.tax_details.TaxDetailsDocument') @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.blueprints.tax_details.get_tax_details_schema_for_corp_entity') @patch('payee.blueprints.tax_details.has_tax_details') def test_validate_tax_details_success_with_payment_entity_id( mock_has_tax_details, mock_get_tax_details_schema_for_corp_entity, mock_get_payee_corp_entity, mock_document, fixture_client, faker, mock_jwt_auth: MockJWTAuth, ): """Test validate tax details success.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] test_corp_entity = faker.pystr() test_payment_entity_id = faker.pyint() test_account_payee_id = faker.pyint() mock_get_payee_corp_entity.return_value = test_corp_entity mock_get_tax_details_schema_for_corp_entity.return_value.return_value.reverse_validate.return_value = {} res = fixture_client.get( f'/account-payee/{test_account_payee_id}/tax-details/validate?payment_entity_id={test_payment_entity_id}', headers=mock_jwt_auth.headers, ) assert res.status_code == 200, res.text assert mock_has_tax_details.call_args_list == [call(test_account_payee_id)] assert not mock_get_payee_corp_entity.called assert mock_get_tax_details_schema_for_corp_entity.call_args_list == [ call(test_payment_entity_id) ] assert mock_document.build_response.call_args_list == [ call(test_account_payee_id, mock_has_tax_details.return_value) ] assert ( mock_get_tax_details_schema_for_corp_entity.return_value.return_value.reverse_validate.call_args_list == [call(mock_document.build_response.return_value)] ) @patch('payee.blueprints.tax_details.TaxDetailsDocument') @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.blueprints.tax_details.get_tax_details_schema_for_corp_entity') @patch('payee.blueprints.tax_details.has_tax_details') def test_validate_tax_details_failure_auth( mock_has_tax_details, mock_get_tax_details_schema_for_corp_entity, mock_get_payee_corp_entity, mock_document, fixture_client, faker, ): """Test validate tax details failure auth.""" test_corp_entity = faker.pystr() test_account_payee_id = faker.pyint() mock_get_payee_corp_entity.return_value = test_corp_entity res = fixture_client.get( f'/account-payee/{test_account_payee_id}/tax-details/validate' ) assert res.status_code == 401, res.text assert not mock_has_tax_details.called @patch('payee.blueprints.tax_details.TaxDetailsDocument') @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.blueprints.tax_details.get_tax_details_schema_for_corp_entity') @patch('payee.blueprints.tax_details.has_tax_details') def test_validate_tax_details_failure_no_document( mock_has_tax_details, mock_get_tax_details_schema_for_corp_entity, mock_get_payee_corp_entity, mock_document, fixture_client, faker, mock_jwt_auth: MockJWTAuth, ): """Test validate tax details failure no document.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] test_corp_entity = faker.pystr() test_account_payee_id = faker.pyint() mock_get_payee_corp_entity.return_value = test_corp_entity mock_has_tax_details.return_value = None res = fixture_client.get( f'/account-payee/{test_account_payee_id}/tax-details/validate', headers=mock_jwt_auth.headers, ) assert res.status_code == 404, res.text assert mock_has_tax_details.call_args_list == [call(test_account_payee_id)] assert not mock_get_payee_corp_entity.called assert not mock_document.build_response.called assert not mock_get_tax_details_schema_for_corp_entity.called @patch('payee.blueprints.tax_details.TaxDetailsDocument') @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.blueprints.tax_details.get_tax_details_schema_for_corp_entity') @patch('payee.blueprints.tax_details.has_tax_details') def test_validate_tax_details_failure_not_valid_details( mock_has_tax_details, mock_get_tax_details_schema_for_corp_entity, mock_get_payee_corp_entity, mock_document, fixture_client, faker, mock_jwt_auth: MockJWTAuth, ): """Test validate tax details success.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] test_corp_entity = faker.pystr() test_account_payee_id = faker.pyint() test_errors = {'error': 'some error'} mock_get_payee_corp_entity.return_value = test_corp_entity mock_get_tax_details_schema_for_corp_entity.return_value.return_value.reverse_validate.return_value = test_errors res = fixture_client.get( f'/account-payee/{test_account_payee_id}/tax-details/validate', headers=mock_jwt_auth.headers, ) assert res.status_code == 400, res.text assert res.json == {'code': 'error', 'message': test_errors} assert mock_has_tax_details.call_args_list == [call(test_account_payee_id)] assert mock_get_payee_corp_entity.call_args_list == [call(test_account_payee_id)] assert mock_get_tax_details_schema_for_corp_entity.call_args_list == [ call(test_corp_entity) ] assert mock_document.build_response.call_args_list == [ call(test_account_payee_id, mock_has_tax_details.return_value) ] assert ( mock_get_tax_details_schema_for_corp_entity.return_value.return_value.reverse_validate.call_args_list == [call(mock_document.build_response.return_value)] )