"""Functional tests for tax details.""" from datetime import datetime from http import HTTPStatus from typing import Any from unittest.mock import MagicMock, Mock, patch, PropertyMock from flask.testing import FlaskClient import pytest import requests from payee.config import Config from payee.constants.constants import ( KNR_VAT_PREFIXES_OMIT_VALIDATION, PAYEE_EVENT_NAMES, PAYMENT_ENTITIES, ) from payee.constants.error import ( ERROR_DONT_HAVE_PERMISSIONS, ERROR_HMRC_API_UNREACHABLE, ERROR_NO_VALID_IDENTITY_IN_CONTEXT, ERROR_NOT_PERMITTED_IDENTITY, ) from payee.schemas.address import AddressSchema, NonUSAddressSchema from tests.utils.auth import MockJWTAuth from tests.utils.factories import AddressFactory account_payee_id = 1 @pytest.mark.parametrize('use_jwt_identity', (True, False)) @patch('payee.blueprints.tax_details.build_tax_details_response') @patch('payee.blueprints.tax_details.has_tax_details') @patch('payee.utils.permissions.validate_multiple_record_owner') def test_get_tax_details_success( mocked_validate_multiple_record_owner: Mock, mocked_has_tax_details: Mock, mocked_build_tax_details_response: Mock, fixture_client: FlaskClient, mock_payee_vat_registered_tax_details: dict[str, str | int], mock_jwt_auth: MockJWTAuth, use_jwt_identity: bool, ) -> None: """Get Tax details.""" if use_jwt_identity: mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] mock_payee_document = { 'vat_number': 'GB821018768', 'local_tax_id': '821018768', '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', } mocked_has_tax_details.return_value = mock_payee_document mocked_build_tax_details_response.return_value = { **mock_payee_vat_registered_tax_details, 'local_tax_id': '821018768', 'account_payee_id': account_payee_id, } mocked_validate_multiple_record_owner.return_value = ( {} if use_jwt_identity else {account_payee_id: True} ) res = fixture_client.get( f'/account-payee/{account_payee_id}/tax-details', headers=(mock_jwt_auth.headers if use_jwt_identity else None), ) assert res.status_code == HTTPStatus.OK assert res.json == { 'account_payee_id': account_payee_id, 'vat_number': mock_payee_document['vat_number'], 'local_tax_id': mock_payee_document['local_tax_id'], 'business_name': mock_payee_document['business_name'], 'business_number': mock_payee_document['business_number'], 'country_of_tax_residency_code': mock_payee_document[ 'country_of_tax_residency_code' ], 'address': { 'country_code': mock_payee_document['country_code'], 'address_1': mock_payee_document['address_1'], 'address_2': mock_payee_document['address_2'], 'city': mock_payee_document['city'], 'province': mock_payee_document['province'], 'zip': mock_payee_document['zip'], }, } @pytest.mark.parametrize( 'use_jwt_identity,incorrect_identity', ((True, True), (True, False), (False, True)), ) @patch('payee.blueprints.tax_details.build_tax_details_response') @patch('payee.blueprints.tax_details.has_tax_details') @patch('payee.utils.permissions.validate_multiple_record_owner') def test_get_tax_details_failure_authorize( mocked_validate_multiple_record_owner: Mock, mocked_has_tax_details: Mock, mocked_build_tax_details_response: Mock, fixture_client: FlaskClient, mock_payee_vat_registered_tax_details: dict[str, str | int], mock_jwt_auth: MockJWTAuth, use_jwt_identity: bool, incorrect_identity: bool, ) -> None: """Check tax details authorize failure.""" mock_jwt_auth.identity = 'abc' mocked_validate_multiple_record_owner.return_value = {account_payee_id: False} res = fixture_client.get( f'/account-payee/{account_payee_id}/tax-details', headers=mock_jwt_auth.headers if use_jwt_identity and not incorrect_identity else None, ) assert res.status_code == HTTPStatus.UNAUTHORIZED assert res.json == { 'error': ', '.join( ( ( ERROR_NO_VALID_IDENTITY_IN_CONTEXT if incorrect_identity else ERROR_NOT_PERMITTED_IDENTITY.format( jwt_identity=mock_jwt_auth.identity ) ), ERROR_DONT_HAVE_PERMISSIONS, ) ) } mocked_has_tax_details.assert_not_called() mocked_build_tax_details_response.assert_not_called() @patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) def test_get_tax_details_error_document_not_exists( _, fixture_client: FlaskClient ) -> None: """Get Tax details error.""" res = fixture_client.get(f'/account-payee/{account_payee_id}/tax-details') assert res.status_code == HTTPStatus.NOT_FOUND @pytest.mark.parametrize('use_jwt_identity', (True, False)) @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.utils.permissions.validate_multiple_record_owner') @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) def test_create_tax_details_non_vat_registered_success( mock_emit: Mock, mock_current_timestamp: Mock, mock_ows_headers: Mock, mock_validate_multiple_record_owner: Mock, mock_get_payee_corp_entity: Mock, mock_kafka_producers: Mock, mock_datetime_object: datetime, fixture_client: FlaskClient, mock_headers: dict[str, str], mock_jwt_auth: MockJWTAuth, use_jwt_identity: bool, ) -> None: """Test create tax details for non vat registered users.""" if use_jwt_identity: mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] mock_validate_multiple_record_owner.return_value = {account_payee_id: True} mock_get_payee_corp_entity.return_value = PAYMENT_ENTITIES.AWAL_UK mock_kafka_producers.return_value = { PAYEE_EVENT_NAMES.VAT_COLLECTED: MagicMock(produce_event=MagicMock()), } post_data = {'vat_number': None, 'country_of_tax_residency_code': 'USA'} mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=(mock_jwt_auth.headers if use_jwt_identity else None), ) res_data = res.json assert res.status_code == HTTPStatus.CREATED assert ( res_data['country_of_tax_residency_code'] == post_data['country_of_tax_residency_code'] ) assert res_data['vat_number'] == post_data['vat_number'] mock_emit.assert_called_once_with( account_payee_id=account_payee_id, action_name=PAYEE_EVENT_NAMES.VAT_COLLECTED ) @patch('payee.blueprints.tax_details.get_payee_corp_entity', return_value='') @patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) def test_create_tax_details_error_corp_entity( mock_validate_multiple_record_owner: Mock, mock_get_payee_corp_entity: Mock, fixture_client: FlaskClient, ) -> None: """Test create tax details for non vat registered users.""" post_data = {'vat_number': None, 'country_of_tax_residency_code': 'USA'} res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == HTTPStatus.BAD_REQUEST assert res_data['code'] == 'error' assert res_data['message'] == 'User is not signed to valid corporate entity: ""' @pytest.mark.parametrize('use_jwt_identity', (True, False)) @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.utils.permissions.validate_multiple_record_owner') @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) @patch('payee.connectors.uk_gov.validate_vat_number', return_value=True) def test_create_tax_details_vat_registered_success( mock_validate_vat_number: Mock, mock_emit: Mock, mock_current_timestamp: Mock, mock_ows_headers: Mock, mock_validate_multiple_record_owner: Mock, mock_get_payee_corp_entity: Mock, mock_kafka_producers: Mock, fixture_client: FlaskClient, mock_payee_vat_registered_tax_details: dict[str, str], mock_datetime_object: datetime, mock_headers: dict[str, str], mock_jwt_auth: MockJWTAuth, use_jwt_identity: bool, ) -> None: """Test create tax details with valid params.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] mock_validate_multiple_record_owner.return_value = {account_payee_id: True} mock_get_payee_corp_entity.return_value = PAYMENT_ENTITIES.AWAL_UK mock_kafka_producers.return_value = { PAYEE_EVENT_NAMES.VAT_COLLECTED: MagicMock(produce_event=MagicMock()) } post_data = mock_payee_vat_registered_tax_details mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=(mock_jwt_auth.headers if use_jwt_identity else None), ) res_data = res.json assert res.status_code == HTTPStatus.CREATED assert res_data['vat_number'] == post_data['vat_number'] assert res_data['address'] == post_data['address'] assert ( res_data['country_of_tax_residency_code'] == post_data['country_of_tax_residency_code'] ) assert res_data['business_number'] == post_data['business_number'] assert res_data['business_name'] == post_data['business_name'] @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) @patch('payee.connectors.uk_gov.validate_vat_number', return_value=True) def test_create_tax_details_vat_registered_empty_address2( mock_validate_vat_number: Mock, mock_emit: Mock, mock_current_timestamp: Mock, mock_ows_headers: Mock, mock_get_payee_corp_entity: Mock, mock_kafka_producers: Mock, fixture_client: FlaskClient, mock_payee_vat_registered_tax_details: dict[str, str], mock_datetime_object: datetime, mock_headers: dict[str, str], mock_jwt_auth: MockJWTAuth, ) -> None: """Test create tax details with valid params.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] mock_kafka_producers.return_value = { PAYEE_EVENT_NAMES.VAT_COLLECTED: MagicMock(produce_event=MagicMock()), } post_data = mock_payee_vat_registered_tax_details post_data['address']['address_2'] = '' mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_jwt_auth.headers, ) res_data = res.json assert res.status_code == HTTPStatus.CREATED assert res_data['vat_number'] == post_data['vat_number'] assert res_data['address'] == post_data['address'] assert ( res_data['country_of_tax_residency_code'] == post_data['country_of_tax_residency_code'] ) assert res_data['business_number'] == post_data['business_number'] assert res_data['business_name'] == post_data['business_name'] @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) def test_create_tax_details_vat_registered_bad_params( _, fixture_client: FlaskClient, mock_payee_vat_registered_tax_details: dict[str, str | None], ) -> None: """Test failure of creating tax details because of invalid params.""" post_data = mock_payee_vat_registered_tax_details post_data['country_code'] = None res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == HTTPStatus.BAD_REQUEST assert res_data['code'] == 'error' assert type(res_data.get('message')) is dict assert 'country_code' in res_data.get('message').keys() @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) def test_create_tax_details_vat_registered_error_business_info( _, fixture_client: FlaskClient, mock_payee_vat_registered_tax_details: dict[str, str | None], ) -> None: """Test failure of creating tax details because of invalid params.""" post_data = mock_payee_vat_registered_tax_details post_data['business_name'] = None res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == HTTPStatus.BAD_REQUEST assert res_data['code'] == 'error' assert type(res_data.get('message')) is dict assert 'business_name' in res_data.get('message').keys() @patch('payee.connectors.uk_gov.requests.get') @patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) @patch('payee.schemas.tax_details.sentry.send_to_sentry') @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch( 'payee.connectors.uk_gov.get_hmrc_token', return_value='token1', ) def test_create_tax_details_vat_registered_error_on_uk_vat_timeout( _, mock_current_timestamp: Mock, mock_ows_headers: Mock, mock_sentry: Mock, mock_get_payee_corp_entity: Mock, mock_get_uk_gov: Mock, fixture_client: FlaskClient, mock_payee_vat_registered_tax_details: dict[str, str], mock_headers: dict[str, str], mock_datetime_object: datetime, ) -> None: """Test failure of creating tax details because of invalid params.""" post_data = mock_payee_vat_registered_tax_details mock_get_uk_gov.side_effect = requests.exceptions.ConnectTimeout( ERROR_HMRC_API_UNREACHABLE ) mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) assert mock_sentry.call_count == 1 res_data = res.json assert res_data['code'] == 'error' assert res.status_code == HTTPStatus.BAD_REQUEST @patch('payee.schemas.tax_details.sentry.send_to_sentry') @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) @patch( 'payee.connectors.uk_gov.get_hmrc_token', return_value='token1', ) def test_create_tax_details_vat_registered_success_on_uk_vat_timeout_with_vat_bypass( _, mock_emit, mock_current_timestamp, mock_ows_headers, mock_sentry, fixture_client, mock_payee_vat_registered_tax_details, mocker, mock_bypass_headers, mock_datetime_object, ): """Test of creating tax details. Test success of creating tax details with HMRC timeout but `force_bypass_vat` param is True and appropriate role in headers. """ mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) post_data = mock_payee_vat_registered_tax_details mocker.patch( 'payee.connectors.uk_gov.requests.get', side_effect=requests.exceptions.ConnectTimeout(ERROR_HMRC_API_UNREACHABLE), ) mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_bypass_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details?force_bypass_vat=1', json=post_data, headers=mock_bypass_headers, ) assert mock_sentry.call_count == 2 res_data = res.json assert res.status_code == 201 assert res_data['vat_number'] == post_data['vat_number'] assert res_data['address'] == post_data['address'] assert ( res_data['country_of_tax_residency_code'] == post_data['country_of_tax_residency_code'] ) assert res_data['business_number'] == post_data['business_number'] assert res_data['business_name'] == post_data['business_name'] def test_get_tax_details_error_owner_validation(mocker, fixture_client): """Get Tax info.""" mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) res = fixture_client.get(f'/account-payee/{account_payee_id}/tax-details') assert res.status_code == HTTPStatus.UNAUTHORIZED assert ( res.json['error'] == f'{ERROR_NO_VALID_IDENTITY_IN_CONTEXT}, {ERROR_DONT_HAVE_PERMISSIONS}' ) def test_create_tax_details_non_vat_registered_error_owner_validation( mocker, fixture_client ): """Test create tax info for non vat registered users.""" mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: False}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) post_data = {'vat_number': None, 'country_of_tax_residency_code': 'USA'} res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) assert res.status_code == 401 assert ( res.json['error'] == f'{ERROR_NO_VALID_IDENTITY_IN_CONTEXT}, {ERROR_DONT_HAVE_PERMISSIONS}' ) def test_create_tax_details_non_vat_registered_error_country_code( mocker, fixture_client ): """Test create tax info for non vat registered users.""" mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) post_data = {'vat_number': None, 'country_of_tax_residency_code': 'asd'} res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) assert res.status_code == 400 assert res.json['code'] == 'error' assert res.json['message'] == { 'country_of_tax_residency_code': ['Country code not recognized: asd'] } def test_create_knr_details_vat_registered_gb_error_format(mocker, fixture_client): """Test failure of creating knr details because of invalid GB vat format.""" post_data = { 'vat_number': 'GB821018768XXX', 'country_of_tax_residency_code': 'USA', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == 400 assert res_data['code'] == 'error' assert type(res_data.get('message')) is dict assert 'vat_number' in res_data.get('message').keys() def test_create_knr_details_vat_registered_error_eu_format(mocker, fixture_client): """Test failure of creating knr details because of invalid EU vat format.""" post_data = { 'vat_number': 'SI12345678910', 'country_of_tax_residency_code': 'USA', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == 400 assert res_data['code'] == 'error' assert type(res_data.get('message')) is dict assert 'vat_number' in res_data.get('message').keys() @patch('payee.schemas.tax_details.sentry.send_to_sentry') @patch('payee.connectors.vies_api.zeep.Client') def test_create_knr_details_vat_registered_error_api_eu_format_force_bypass( mock_zeep, mock_sentry, mocker, fixture_client, mock_bypass_headers, mock_identity_fields, ): """Test of creating knr details with EU vat format. Success of creating knr details because with Error from View api but 'force_bypass_vat'=True and appropriate role in headers. """ post_data = { 'vat_number': 'SI12345678', 'country_of_tax_residency_code': 'USA', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch('payee.logic.tax_details.emit_payee_event', return_value=True) mocker.patch( 'payee.logic.tax_details.get_audit_fields', return_value=mock_identity_fields ) mock_zeep.side_effect = Exception('Api error!') res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details?force_bypass_vat=1', json=post_data, headers=mock_bypass_headers, ) assert mock_sentry.call_count == 2 res_data = res.json assert res.status_code == 201 assert res_data == { 'account_payee_id': account_payee_id, **post_data, **mock_identity_fields, 'revision': '0', 'local_tax_id': None, } def test_create_knr_details_dummy_vat( mocker, fixture_client, mock_bypass_headers, mock_identity_fields ): """Test of creating knr details with KNR_DUMMY_VAT vat.""" post_data = { 'vat_number': 'KNR_DUMMY_VAT', 'country_of_tax_residency_code': 'USA', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.logic.tax_details.get_audit_fields', return_value=mock_identity_fields ) mocker.patch('payee.logic.tax_details.emit_payee_event', return_value=True) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_bypass_headers, ) res_data = res.json assert res.status_code == 201 assert res_data == { 'account_payee_id': account_payee_id, **post_data, **mock_identity_fields, 'revision': '0', 'local_tax_id': None, } @pytest.mark.parametrize('country', KNR_VAT_PREFIXES_OMIT_VALIDATION) def test_create_knr_details_omit_vat_validation_vat( country, mocker, fixture_client, mock_bypass_headers, mock_identity_fields ): """Test of creating knr details omit valildation.""" post_data = { 'vat_number': f'{country}1234567', 'country_of_tax_residency_code': 'USA', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.logic.tax_details.get_audit_fields', return_value=mock_identity_fields ) mocker.patch('payee.logic.tax_details.emit_payee_event', return_value=True) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_bypass_headers, ) res_data = res.json assert res.status_code == 201 assert res_data == { 'account_payee_id': account_payee_id, **post_data, **mock_identity_fields, 'revision': '0', 'local_tax_id': None, } @patch('payee.schemas.tax_details.sentry.send_to_sentry') @patch('payee.connectors.vies_api.zeep.Client') def test_create_knr_details_eu_format_force_bypass_without_needed_role( mock_zeep, mock_sentry, mocker, fixture_client, mock_headers ): """Test of creating knr details with EU vat format. Success of creating knr details because with Error from View api but only with 'force_bypass_vat'=True. """ post_data = { 'vat_number': 'SI12345678', 'country_of_tax_residency_code': 'USA', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch('payee.logic.tax_details.emit_payee_event', return_value=True) mock_zeep.side_effect = Exception('Api error!') res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details?force_bypass_vat=1', json=post_data, headers=mock_headers, ) assert mock_sentry.call_count == 1 res_data = res.json assert res.status_code == 400 assert res_data['code'] == 'error' assert type(res_data.get('message')) is dict assert 'vat_number' in res_data.get('message').keys() @patch('payee.schemas.tax_details.sentry.send_to_sentry') @patch( 'payee.connectors.uk_gov.get_hmrc_token', return_value='token1', ) def test_create_knr_details_vat_registered_error_api_gb_format_force_bypass( _, mock_sentry, mocker, fixture_client, mock_bypass_headers, mock_identity_fields ): """Test of creating knr details with EU vat format. Success of creating knr details because with Error from View api but 'force_bypass_vat': True. """ post_data = { 'vat_number': 'GB123456789', 'country_of_tax_residency_code': 'USA', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'New York', 'city': 'Brooklyn', 'zip': '80021', 'country_code': 'UKR', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.connectors.uk_gov.requests.get', side_effect=requests.exceptions.ConnectTimeout(ERROR_HMRC_API_UNREACHABLE), ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.logic.tax_details.get_audit_fields', return_value=mock_identity_fields ) mocker.patch('payee.logic.tax_details.emit_payee_event', return_value=True) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details?force_bypass_vat=1', json=post_data, headers=mock_bypass_headers, ) assert mock_sentry.call_count == 2 res_data = res.json assert res.status_code == 201 assert res_data == { 'account_payee_id': account_payee_id, **post_data, **mock_identity_fields, 'revision': '0', 'local_tax_id': None, } @patch('payee.connectors.vies_api.zeep.Client') def test_create_knr_details_vat_registered_eu_format( mock_zeep, mocker, mock_headers, fixture_client, mock_identity_fields ): """Test of success creating knr details.""" post_data = { 'vat_number': 'SI64875318', 'country_of_tax_residency_code': 'SVN', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'Ljubljana', 'city': 'Ljubljana', 'zip': '1000', 'country_code': 'SVN', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) mocker.patch('payee.logic.tax_details.emit_payee_event', return_value=True) mocker.patch( 'payee.logic.tax_details.get_audit_fields', return_value=mock_identity_fields ) mock_zeep.return_value = MagicMock( service=MagicMock(checkVatApprox=MagicMock(return_value={'valid': True})) ) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_headers, ) res_data = res.json assert res_data == { 'account_payee_id': account_payee_id, **post_data, **mock_identity_fields, 'revision': '0', 'local_tax_id': None, } assert res.status_code == 201 @patch('payee.connectors.vies_api.zeep.Client') def test_create_knr_details_non_vat_registered_eu_format( mock_zeep, mocker, mock_headers, fixture_client, mock_identity_fields ): """Test of success creating knr details.""" post_data = { 'vat_number': None, 'country_of_tax_residency_code': 'SVN', 'address': { 'address_1': 'down the lane1', 'address_2': 'down the lane2', 'province': 'Ljubljana', 'city': 'Ljubljana', 'zip': '1000', 'country_code': 'SVN', }, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) mocker.patch('payee.logic.tax_details.emit_payee_event', return_value=True) mocker.patch( 'payee.logic.tax_details.get_audit_fields', return_value=mock_identity_fields ) mock_zeep.return_value = MagicMock( service=MagicMock(checkVatApprox=MagicMock(return_value={'valid': True})) ) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_headers, ) res_data = res.json assert res_data == { 'account_payee_id': account_payee_id, **post_data, **mock_identity_fields, 'revision': '0', 'local_tax_id': None, } assert res.status_code == 201 @patch('payee.connectors.vies_api.zeep.Client') def test_create_knr_details_non_vat_registered_eu_format_error_address( mock_zeep, mocker, mock_headers, fixture_client, mock_identity_fields ): """Test failure of creating knr details because address is required.""" post_data = { 'vat_number': None, 'country_of_tax_residency_code': 'SVN', 'address': None, 'business_name': 'business_number', 'business_number': 'business_number', } mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.KNR_NL, ) mocker.patch('payee.logic.tax_details.emit_payee_event', return_value=True) mocker.patch( 'payee.logic.tax_details.get_audit_fields', return_value=mock_identity_fields ) mock_zeep.return_value = MagicMock( service=MagicMock(checkVatApprox=MagicMock(return_value={'valid': True})) ) res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_headers, ) res_data = res.json assert res.status_code == 400 assert res_data['code'] == 'error' assert type(res_data.get('message')) is dict assert 'address' in res_data.get('message').keys() @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.connectors.uk_gov.validate_vat_number', return_value=True) def test_create_tax_details_ows_headers_error( mock_validate_vat_number, mock_current_timestamp, mock_ows_headers, fixture_client, mock_payee_vat_registered_tax_details, mocker, mock_datetime_object, ): """Test failure of creating tax details because of invalid params.""" mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) post_data = mock_payee_vat_registered_tax_details mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = {'headers': 'error'} res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) assert res.status_code == 500 @patch('payee.logic.tax_details.emit_payee_event', return_value=True) def test_resync_payment_readiness_by_account_payee_id( mock_emit, mocker, fixture_client, monkeypatch, mock_headers ): """Test resync_payment_readiness_by_account_payee_id.""" mocker.patch( 'payee.blueprints.tax_details.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mock_kafka_producers = { PAYEE_EVENT_NAMES.RESYNC_PAYMENT_READINESS: MagicMock( produce_event=MagicMock() ), } monkeypatch.setattr( 'payee.config.Config.KAFKA_PRODUCERS_BY_ACTION_NAME', mock_kafka_producers ) res = fixture_client.post( f'/account-payee/{account_payee_id}/resync-payment-readiness', ) assert res.status_code == 201 mock_emit.assert_called_once_with( account_payee_id=account_payee_id, action_name=PAYEE_EVENT_NAMES.RESYNC_PAYMENT_READINESS, ) @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) def test_create_tax_details_non_vat_registered_ff_enabled( mock_emit, mock_current_timestamp, mock_ows_headers, mock_datetime_object, mocker, fixture_client, monkeypatch, mock_headers, ): """Test to create tax details for non vat registered users.""" mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.AWAL_UK, ) mock_kafka_producers = { PAYEE_EVENT_NAMES.VAT_COLLECTED: MagicMock(produce_event=MagicMock()), } monkeypatch.setattr( 'payee.config.Config.KAFKA_PRODUCERS_BY_ACTION_NAME', mock_kafka_producers ) post_data = {'vat_number': None, 'country_of_tax_residency_code': 'USA'} mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == 201 assert ( res_data['country_of_tax_residency_code'] == post_data['country_of_tax_residency_code'] ) assert res_data['vat_number'] == post_data['vat_number'] mock_emit.assert_called_once_with( account_payee_id=account_payee_id, action_name=PAYEE_EVENT_NAMES.VAT_COLLECTED ) @pytest.mark.parametrize( 'address_2,province,missing_fields', ( ('down the lane2', 'New York', False), (None, 'New York', False), ('down the lane2', None, False), ('', '', False), (None, None, True), ), ) @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.utils.permissions.validate_multiple_record_owner') @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) def test_create_es_tax_details_vat_registered( mock_emit: Mock, mock_current_timestamp: Mock, mock_ows_headers: Mock, mock_validate_multiple_record_owner: Mock, mock_get_payee_corp_entity: Mock, mock_kafka_producers: Mock, fixture_client: FlaskClient, mock_payee_es_vat_registered_tax_details: dict[str, Any], mock_datetime_object: datetime, mock_headers: dict[str, str], address_2: str | None, province: str | None, missing_fields: bool, ): """Test create tax details with valid params.""" post_data = dict(mock_payee_es_vat_registered_tax_details) post_data['address'] = dict(post_data['address']) if missing_fields: del post_data['address']['address_2'] del post_data['address']['province'] else: post_data['address']['address_2'] = address_2 post_data['address']['province'] = province mock_validate_multiple_record_owner.return_value = {account_payee_id: True} mock_get_payee_corp_entity.return_value = PAYMENT_ENTITIES.ORCHARD_ES mock_kafka_producers.return_value = { PAYEE_EVENT_NAMES.VAT_COLLECTED: MagicMock(produce_event=MagicMock()), } mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == HTTPStatus.CREATED assert res_data['vat_number'] == f'ES{post_data["local_tax_id"]}' assert res_data['local_tax_id'] == post_data['local_tax_id'] if not address_2 or missing_fields: post_data['address']['address_2'] = '' if not province or missing_fields: post_data['address']['province'] = None assert res_data['address'] == post_data['address'] @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) def test_create_es_tax_details_non_vat_registered( mock_emit, mock_current_timestamp, mock_ows_headers, mocker, fixture_client, mock_payee_es_vat_registered_tax_details, mock_datetime_object, mock_headers, monkeypatch, ): """Test create tax details with valid params.""" mocker.patch( 'payee.utils.permissions.validate_multiple_record_owner', return_value={account_payee_id: True}, ) mocker.patch( 'payee.blueprints.tax_details.get_payee_corp_entity', return_value=PAYMENT_ENTITIES.ORCHARD_ES, ) mock_kafka_producers = { PAYEE_EVENT_NAMES.VAT_COLLECTED: MagicMock(produce_event=MagicMock()), } monkeypatch.setattr( 'payee.config.Config.KAFKA_PRODUCERS_BY_ACTION_NAME', mock_kafka_producers ) post_data = mock_payee_es_vat_registered_tax_details del post_data['address'] post_data['is_vat_registered'] = False mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == 201 assert res_data['local_tax_id'] == post_data['local_tax_id'] assert res_data['vat_number'] == None assert res_data['address'] == None @pytest.mark.parametrize( 'address_2,province,missing_fields', ( ('down the lane2', 'New York', False), (None, 'New York', False), ('down the lane2', None, False), ('', '', False), (None, None, True), ), ) @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.utils.permissions.validate_multiple_record_owner') @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) def test_create_de_tax_details( mock_emit: Mock, mock_current_timestamp: Mock, mock_ows_headers: Mock, mock_validate_multiple_record_owner: Mock, mock_get_payee_corp_entity: Mock, mock_kafka_producers: Mock, fixture_client: FlaskClient, mock_payee_de_tax_details: dict[str, Any], mock_datetime_object: datetime, mock_headers: dict[str, str], address_2: str | None, province: str | None, missing_fields: bool, ): """Test create tax details with valid params.""" post_data = dict(mock_payee_de_tax_details) post_data['address'] = dict(post_data['address']) if missing_fields: del post_data['address']['address_2'] del post_data['address']['province'] else: post_data['address']['address_2'] = address_2 post_data['address']['province'] = province mock_validate_multiple_record_owner.return_value = {account_payee_id: True} mock_get_payee_corp_entity.return_value = PAYMENT_ENTITIES.ORCHARD_DE mock_kafka_producers.return_value = { PAYEE_EVENT_NAMES.VAT_COLLECTED: MagicMock(produce_event=MagicMock()), } mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == HTTPStatus.CREATED assert res_data['vat_number'] == post_data['vat_number'] assert res_data['local_tax_id'] == post_data['local_tax_id'] if not address_2 or missing_fields: post_data['address']['address_2'] = '' if not province or missing_fields: post_data['address']['province'] = None assert res_data['address'] == post_data['address'] @pytest.mark.parametrize( 'address_2,province,missing_fields', ( ('down the lane2', 'New York', False), (None, 'New York', False), ('down the lane2', None, False), ('', '', False), (None, None, True), ), ) @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.blueprints.tax_details.get_payee_corp_entity') @patch('payee.utils.permissions.validate_multiple_record_owner') @patch('payee.logic.secure_document.flask_request.get_ows_headers') @patch('payee.logic.secure_document.current_timestamp') @patch('payee.logic.tax_details.emit_payee_event', return_value=True) def test_create_no_tax_details( mock_emit: Mock, mock_current_timestamp: Mock, mock_ows_headers: Mock, mock_validate_multiple_record_owner: Mock, mock_get_payee_corp_entity: Mock, mock_kafka_producers: Mock, fixture_client: FlaskClient, mock_payee_no_tax_details: dict[str, Any], mock_datetime_object: datetime, mock_headers: dict[str, str], address_2: str | None, province: str | None, missing_fields: bool, ): """Test create tax details with valid params.""" post_data = dict(mock_payee_no_tax_details) post_data['address'] = dict(post_data['address']) if missing_fields: del post_data['address']['address_2'] del post_data['address']['province'] else: post_data['address']['address_2'] = address_2 post_data['address']['province'] = province mock_validate_multiple_record_owner.return_value = {account_payee_id: True} mock_get_payee_corp_entity.return_value = PAYMENT_ENTITIES.ORCHARD_NO mock_kafka_producers.return_value = { PAYEE_EVENT_NAMES.VAT_COLLECTED: MagicMock(produce_event=MagicMock()), } mock_current_timestamp.return_value = mock_datetime_object mock_ows_headers.return_value = mock_headers res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data ) res_data = res.json assert res.status_code == HTTPStatus.CREATED assert res_data['vat_number'] == post_data['vat_number'] if not address_2 or missing_fields: post_data['address']['address_2'] = '' if not province or missing_fields: post_data['address']['province'] = None assert res_data['address'] == post_data['address'] def test_address_schema_ag_zip_not_required(): """Test that AddressSchema does not require zip for ATG (Antigua and Barbuda).""" address = AddressFactory.build() address['country_code'] = 'ATG' del address['zip'] # Remove zip field result = AddressSchema().load(address) assert result['country_code'] == 'ATG' assert 'zip' not in result @pytest.mark.parametrize('country_code', ['USA', 'GBR']) def test_address_schema_zip_required_for_us_gb(country_code): """Test that AddressSchema requires zip for USA and GBR.""" address = AddressFactory.build() address['country_code'] = country_code del address['zip'] # Remove zip field with pytest.raises(Exception) as exc_info: AddressSchema().load(address) # Should fail because zip is required for non-ATG countries assert 'zip' in str(exc_info.value) or 'required' in str(exc_info.value).lower() @pytest.mark.parametrize('country_code', ['ATG', 'NOR']) # NOR = Norway def test_non_us_address_schema_zip_not_required_ag_norway(country_code): """Test that NonUSAddressSchema does not require zip for ATG and Norway.""" address = AddressFactory.build() address['country_code'] = country_code del address['zip'] # Remove zip field result = NonUSAddressSchema().load(address) assert result['country_code'] == country_code assert 'zip' not in result @pytest.mark.parametrize( 'payment_entity', ( PAYMENT_ENTITIES.ORCHARD_ES, PAYMENT_ENTITIES.ORCHARD_DE, PAYMENT_ENTITIES.AWAL_UK, PAYMENT_ENTITIES.ORCHARD_UK, PAYMENT_ENTITIES.ORCHARD_NO, PAYMENT_ENTITIES.KNR_NL, PAYMENT_ENTITIES.KNR_UK, ), ) @patch('payee.schemas.tax_details.Vies') @patch('payee.connectors.uk_gov.validate_vat_number', return_value=True) @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.logic.tax_details.emit_payee_event', return_value=True) @patch('payee.blueprints.tax_details.get_payee_corp_entity') def test_validate_tax_details_success( mock_get_payee_corp_entity: Mock, mock_emit_payee_event: Mock, mock_kafka_producers: Mock, mock_validate_vat_number: Mock, mock_vies: Mock, payment_entity, fixture_client: FlaskClient, mock_payee_es_vat_registered_tax_details: dict[str, Any], mock_payee_eu_vat_registered_tax_details: dict[str, Any], mock_payee_gb_vat_registered_tax_details: dict[str, Any], mock_payee_de_tax_details: dict[str, Any], mock_payee_no_tax_details: dict[str, Any], mock_payee_es_non_vat_registered_tax_details, mock_jwt_auth: MockJWTAuth, ): """Test create tax details with valid params and validate then.""" fixture = { PAYMENT_ENTITIES.ORCHARD_ES: mock_payee_es_vat_registered_tax_details, PAYMENT_ENTITIES.ORCHARD_DE: mock_payee_de_tax_details, PAYMENT_ENTITIES.AWAL_UK: mock_payee_gb_vat_registered_tax_details, PAYMENT_ENTITIES.ORCHARD_UK: mock_payee_gb_vat_registered_tax_details, PAYMENT_ENTITIES.ORCHARD_NO: mock_payee_no_tax_details, PAYMENT_ENTITIES.KNR_NL: mock_payee_eu_vat_registered_tax_details, PAYMENT_ENTITIES.KNR_UK: mock_payee_eu_vat_registered_tax_details, }.get(payment_entity) mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] post_data = dict(fixture) mock_get_payee_corp_entity.return_value = payment_entity res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.CREATED, res.text res = fixture_client.get( f'/account-payee/{account_payee_id}/tax-details/validate', headers=mock_jwt_auth.headers, ) assert res.status_code == 200, res.text @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.logic.tax_details.emit_payee_event', return_value=True) @patch('payee.blueprints.tax_details.get_payee_corp_entity') def test_validate_tax_details_failure_auth( mock_get_payee_corp_entity: Mock, mock_emit_payee_event: Mock, mock_kafka_producers: Mock, fixture_client: FlaskClient, mock_payee_es_vat_registered_tax_details: dict[str, Any], mock_jwt_auth: MockJWTAuth, ): """Test create tax details with valid params.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] post_data = dict(mock_payee_es_vat_registered_tax_details) mock_get_payee_corp_entity.return_value = PAYMENT_ENTITIES.ORCHARD_ES res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.CREATED res = fixture_client.get( f'/account-payee/{account_payee_id}/tax-details/validate', ) assert res.status_code == 401, res.text @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.logic.tax_details.emit_payee_event', return_value=True) @patch('payee.blueprints.tax_details.get_payee_corp_entity') def test_validate_tax_details_failure_no_details( mock_get_payee_corp_entity: Mock, mock_emit_payee_event: Mock, mock_kafka_producers: Mock, fixture_client: FlaskClient, mock_payee_es_vat_registered_tax_details: dict[str, Any], mock_jwt_auth: MockJWTAuth, ): """Test create tax details with valid params.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] post_data = dict(mock_payee_es_vat_registered_tax_details) mock_get_payee_corp_entity.return_value = PAYMENT_ENTITIES.ORCHARD_ES res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.CREATED res = fixture_client.get( f'/account-payee/{account_payee_id + 1}/tax-details/validate', headers=mock_jwt_auth.headers, ) assert res.status_code == 404, res.text @patch.object(Config, 'KAFKA_PRODUCERS_BY_ACTION_NAME', new_callable=PropertyMock) @patch('payee.logic.tax_details.emit_payee_event', return_value=True) @patch('payee.blueprints.tax_details.get_payee_corp_entity') def test_validate_tax_details_failure_invalid_details( mock_get_payee_corp_entity: Mock, mock_emit_payee_event: Mock, mock_kafka_producers: Mock, fixture_client: FlaskClient, mock_payee_es_vat_registered_tax_details: dict[str, Any], mock_jwt_auth: MockJWTAuth, ): """Test create tax details with valid params.""" mock_jwt_auth.identity = Config.TAX_FORM_SERVICE_IDENTITIES[0] post_data = dict(mock_payee_es_vat_registered_tax_details) mock_get_payee_corp_entity.return_value = PAYMENT_ENTITIES.ORCHARD_ES res = fixture_client.post( f'/account-payee/{account_payee_id}/tax-details', json=post_data, headers=mock_jwt_auth.headers, ) assert res.status_code == HTTPStatus.CREATED res = fixture_client.get( f'/account-payee/{account_payee_id}/tax-details/validate?payment_entity_id=1', headers=mock_jwt_auth.headers, ) assert res.status_code == 400, res.text