"""Test ows-abacus-account requests.""" from http import HTTPStatus from typing import Any from unittest import mock import httpx from owsclient.test import OwsClientMock import pytest from src.connectors import ows_abacus_account from src.connectors.exceptions import OwsAbacusAccountException from src.models import AccountTaxInfoBulk, UpdateAccountTaxInfo from tests.unit.factories import ( AccountTaxInfoFactory, PaymentHoldResultFactory, ) def test_post_account_payment_hold_success( ows_client_mock: OwsClientMock, ) -> None: """Test create or update payment hold success.""" payment_hold = PaymentHoldResultFactory.build() path = f'/account/{payment_hold.account_id}/payment-hold/' ows_client_mock.post( 'ows-abacus-account', path, json=payment_hold.model_dump( exclude={'payment_hold_id', 'account_id'}, mode='json' ), ).mock( return_value=httpx.Response( 201, json=payment_hold.model_dump(mode='json'), ) ) result = ows_abacus_account.create_or_update_payment_hold(payment_hold) assert result == payment_hold def test_post_account_payment_hold_duplicate(ows_client_mock: OwsClientMock) -> None: """Test create or update payment hold duplicate.""" payment_hold = PaymentHoldResultFactory.build() path = f'/account/{payment_hold.account_id}/payment-hold/' message = ( f"Account's payment status of {'on hold' if payment_hold.is_on_hold else 'active'}" " already exists or is pending" ) ows_client_mock.post( 'ows-abacus-account', path, json=payment_hold.model_dump( exclude={'payment_hold_id', 'account_id'}, mode='json' ), ).mock( return_value=httpx.Response( 400, json={'message': message}, ) ) result = ows_abacus_account.create_or_update_payment_hold(payment_hold) assert not result def test_post_account_payment_hold_error(ows_client_mock: OwsClientMock) -> None: """Test create or update payment hold error.""" payment_hold = PaymentHoldResultFactory.build() path = f'/account/{payment_hold.account_id}/payment-hold/' response = {'message': 'Start date cannot be before today'} ows_client_mock.post( 'ows-abacus-account', path, json=payment_hold.model_dump( exclude={'payment_hold_id', 'account_id'}, mode='json' ), ).mock( return_value=httpx.Response( 400, json=response, ) ) with pytest.raises(OwsAbacusAccountException) as exc: ows_abacus_account.create_or_update_payment_hold(payment_hold) assert str(exc.value) == f'ERROR in POST {path} {response}' @mock.patch('src.connectors.ows_abacus_account.post') def test_get_payees_by_accounts_when_payee_not_found(mock_post: mock.Mock) -> None: """Test get_payees_by_accounts and one of payee not found.""" payee_id_to_account_id = {110: 15} account_ids = ['110', '150'] mock_post.return_value.json.return_value = { 'items': [ {'data': dict(account_id=110, account_payee_id=15)}, {'data': None}, ] } result = ows_abacus_account.get_payees_by_accounts(account_ids) assert result == payee_id_to_account_id mock_post.assert_called_once_with( 'ows-abacus-account', '/account-payee/dataloader/account', body=account_ids, raise_for_status=True, ) @pytest.mark.parametrize('is_error', (True, False)) def test_get_payees_by_accounts(ows_client_mock: OwsClientMock, is_error: bool) -> None: """Test get_payees_by_accounts.""" account_id_to_payee_id = {15: 110, 17: 150, 25: 341} account_ids = list(account_id_to_payee_id.keys()) + [32] if is_error: response = httpx.Response(HTTPStatus.BAD_REQUEST) else: response = httpx.Response( HTTPStatus.OK, json={ 'items': [ { 'data': dict( account_payee_id=account_payee_id, account_id=account_id ) } for account_id, account_payee_id in account_id_to_payee_id.items() ] + [{'data': None}] }, ) ows_client_mock.post( 'ows-abacus-account', '/account-payee/dataloader/account', json=account_ids, ).mock(return_value=response) if is_error: with pytest.raises(OwsAbacusAccountException): ows_abacus_account.get_payees_by_accounts(account_ids) else: result = ows_abacus_account.get_payees_by_accounts(account_ids) assert result == account_id_to_payee_id @pytest.mark.parametrize('is_error', (False, True)) def test_get_account_tax_info_bulk( ows_client_mock: OwsClientMock, is_error: bool ) -> None: """Test get_account_tax_info_bulk.""" account_ids = [15, 11, 201] offset = 3 limit = 12 data_items = AccountTaxInfoFactory.batch(3) ows_client_mock.post( 'ows-abacus-account', f'/accounts/account-tax-info?offset={offset}&limit={limit}', json=account_ids, ).mock( return_value=httpx.Response( HTTPStatus.BAD_REQUEST if is_error else HTTPStatus.OK, json={ 'items': [i.model_dump(mode='json') for i in data_items], 'total_count': 3, }, ) ) if is_error: with pytest.raises(OwsAbacusAccountException): ows_abacus_account.get_account_tax_info_bulk(account_ids, offset, limit) else: result = ows_abacus_account.get_account_tax_info_bulk( account_ids, offset, limit ) assert result == AccountTaxInfoBulk(items=data_items, total_count=3) @pytest.mark.parametrize( 'is_error,data', ( (False, {'country_of_tax_residence': 'AUS'}), ( False, { 'is_resident_of_spanish_islands': True, 'tax_employment_type': 't1', 'certificate_of_residence_expiration_date': '2024-05-11', 'country_of_tax_residence': 'CAN', }, ), (True, {}), ), ) def test_update_account_tax_info( ows_client_mock: OwsClientMock, is_error: bool, data: dict[str, Any] ) -> None: """Test update_account_tax_info.""" account_tax_info_id = 18 ows_client_mock.put( 'ows-abacus-account', f'/account-tax-info/{account_tax_info_id}', json=data, ).mock( return_value=httpx.Response( HTTPStatus.BAD_REQUEST if is_error else HTTPStatus.OK, json=AccountTaxInfoFactory.build(**data).model_dump(mode='json'), ) ) if is_error: with pytest.raises(OwsAbacusAccountException): ows_abacus_account.update_account_tax_info( account_tax_info_id, UpdateAccountTaxInfo(**data) ) else: ows_abacus_account.update_account_tax_info( account_tax_info_id, UpdateAccountTaxInfo(**data) )