"""Test ows-abacus-account requests.""" import typing import urllib.parse from faker import Faker import httpx from owsclient.test import OwsClientMock import pytest from src.connectors.exceptions import OwsAccountException from src.connectors.ows_account import ( account_payee_dataloader, account_payment_term_dataloader, bulk_get_payment_holds, get_account_tax_info, get_accounts, get_eligible_accounts, ) from src.models import Account, GetAccountsResponse from tests.unit.factories import ( AccountFactory, AccountPayeeDataLoaderItemFactory, AccountPayeeDataLoaderResponseFactory, AccountPayeeFactory, AccountPaymentHoldFactory, AccountPaymentTermDataloaderItemFactory, AccountTaxInfoFactory, GetAccountsResponseFactory, ) def test_get_eligible_accounts_success(ows_client_mock: OwsClientMock) -> None: """Test successfully getting eligible accounts.""" eligible_accounts = [AccountFactory.build(), AccountFactory.build()] payment_group_id = 33 ows_client_mock.get( 'ows-abacus-account', f'/payment-group/{payment_group_id}/eligible-accounts' ).mock( return_value=httpx.Response( status_code=200, json=[Account.model_dump(a, mode='json') for a in eligible_accounts], ) ) res = get_eligible_accounts(payment_group_id) assert res == eligible_accounts def test_get_eligible_accounts_failure(ows_client_mock: OwsClientMock) -> None: """Test failure getting eligible accounts.""" payment_group_id = 333 ows_client_mock.get( 'ows-abacus-account', f'/payment-group/{payment_group_id}/eligible-accounts' ).mock(return_value=httpx.Response(status_code=400, json='error')) with pytest.raises( OwsAccountException, match='ERROR in GET /payment-group/333/eligible-accounts' ): get_eligible_accounts(payment_group_id) @pytest.mark.parametrize('agreement_type_ids', [None, [1, 2]]) def test_get_accounts_success( ows_client_mock: OwsClientMock, agreement_type_ids: int | None ) -> None: """Test successfully calling get_accounts.""" accounts_response = GetAccountsResponseFactory.build() params: dict[str, typing.Any] = { 'limit': 100, 'offset': 200, 'reference_payment_type_id': 1, } if agreement_type_ids: params['agreement_type_ids'] = agreement_type_ids query_string = urllib.parse.urlencode(params, doseq=True) ows_client_mock.get('ows-abacus-account', f'/accounts/?{query_string}').mock( return_value=httpx.Response( status_code=200, json=GetAccountsResponse.model_dump(accounts_response, mode='json'), ) ) res = get_accounts(**params) assert res == accounts_response def test_get_accounts_failure(ows_client_mock: OwsClientMock) -> None: """Test failure calling get_accounts.""" params: dict[str, typing.Any] = { 'limit': 100, 'offset': 200, 'reference_payment_type_id': 1, } query_string = urllib.parse.urlencode(params) ows_client_mock.get('ows-abacus-account', f'/accounts/?{query_string}').mock( return_value=httpx.Response(status_code=400, json='error') ) with pytest.raises( OwsAccountException, match=f'ERROR in GET /accounts/\?{query_string}' ): get_accounts(**params) def test_get_account_tax_info_success( ows_client_mock: OwsClientMock, faker: Faker ) -> None: """Test get_account_tax_info success.""" tax_info_items = AccountTaxInfoFactory.batch(faker.pyint(1, 5)) account_ids = faker.pylist(allowed_types=[int]) limit = faker.pyint() offset = faker.pyint() path_pattern = f'/accounts/account-tax-info/?limit={limit}&offset={offset}' ows_client_mock.post('ows-abacus-account', path_pattern, json=account_ids).mock( return_value=httpx.Response( status_code=200, json={ 'items': [item.model_dump(mode='json') for item in tax_info_items], 'total_count': len(tax_info_items), }, ) ) res = get_account_tax_info(account_ids, limit, offset) assert res.items == tax_info_items assert res.total_count == len(tax_info_items) def test_get_account_tax_info_failure( ows_client_mock: OwsClientMock, faker: Faker ) -> None: """Test get_account_tax_info failure.""" account_ids = faker.pylist(allowed_types=[int]) limit = faker.pyint() offset = faker.pyint() path_pattern = f'/accounts/account-tax-info/?limit={limit}&offset={offset}' ows_client_mock.post('ows-abacus-account', path_pattern).mock( return_value=httpx.Response(status_code=400, json='error') ) with pytest.raises( OwsAccountException, match=f'ERROR in POST {path_pattern.replace("?", "\?")}' ): get_account_tax_info(account_ids, limit, offset) def test_account_payment_term_dataloader_success( ows_client_mock: OwsClientMock, faker: Faker ) -> None: """Test account_payment_term dataloader success.""" items = AccountPaymentTermDataloaderItemFactory.batch(faker.pyint(1, 5)) account_ids = faker.pylist(allowed_types=[int]) path_pattern = f'/account/account-payment-term/dataloader' ows_client_mock.post('ows-abacus-account', path_pattern, json=account_ids).mock( return_value=httpx.Response( status_code=200, json=[item.model_dump(mode='json') for item in items], ) ) res = account_payment_term_dataloader(account_ids) assert res == {item.data.account_id: item.data for item in items if item.data} def test_account_payment_term_dataloader_failure( ows_client_mock: OwsClientMock, faker: Faker ) -> None: """Test get_account_payment_term failure.""" account_ids = faker.pylist(allowed_types=[int]) path_pattern = f'/account/account-payment-term/dataloader' ows_client_mock.post('ows-abacus-account', path_pattern, json=account_ids).mock( return_value=httpx.Response(status_code=400, json='error') ) with pytest.raises(OwsAccountException, match=f'ERROR in POST {path_pattern}'): account_payment_term_dataloader(account_ids) def test_account_payee_dataloader_success( ows_client_mock: OwsClientMock, faker: Faker ) -> None: """Test account_payee_dataloader""" mock_payee = AccountPayeeFactory.build() response = AccountPayeeDataLoaderResponseFactory.build( items=[AccountPayeeDataLoaderItemFactory.build(account_payee=mock_payee)] ) account_ids = faker.pylist(allowed_types=[int]) path_pattern = f'/account-payee/dataloader/account' ows_client_mock.post('ows-abacus-account', path_pattern, json=account_ids).mock( return_value=httpx.Response( status_code=200, json={'items': [{'data': mock_payee.model_dump(mode='json')}]}, ) ) res = account_payee_dataloader(account_ids) assert res == {mock_payee.account_id: mock_payee} def test_account_payee_dataloader_failure( ows_client_mock: OwsClientMock, faker: Faker ) -> None: """Test account_payee_dataloader error""" account_ids = faker.pylist(allowed_types=[int]) path_pattern = f'/account-payee/dataloader/account' ows_client_mock.post('ows-abacus-account', path_pattern, json=account_ids).mock( return_value=httpx.Response(status_code=500, json='error') ) with pytest.raises(OwsAccountException, match=f'ERROR in POST {path_pattern}'): account_payee_dataloader(account_ids) def test_bulk_get_payment_holds_success( ows_client_mock: OwsClientMock, faker: Faker ) -> None: """Test bulk_get_payment_holds success.""" payment_holds = AccountPaymentHoldFactory.batch(faker.pyint(1, 5)) account_ids = faker.pylist(allowed_types=[int]) limit = faker.pyint() offset = faker.pyint() query_string = urllib.parse.urlencode({'limit': limit, 'offset': offset}) path_pattern = f'/payment-holds/?{query_string}' ows_client_mock.post('ows-abacus-account', path_pattern, json=account_ids).mock( return_value=httpx.Response( status_code=200, json={ 'items': [hold.model_dump(mode='json') for hold in payment_holds], 'total_count': len(payment_holds), }, ) ) res = bulk_get_payment_holds(account_ids, limit, offset) assert res.items == payment_holds assert res.total_count == len(payment_holds) def test_bulk_get_payment_holds_failure( ows_client_mock: OwsClientMock, faker: Faker ) -> None: """Test bulk_get_payment_holds failure.""" account_ids = faker.pylist(allowed_types=[int]) limit = faker.pyint() offset = faker.pyint() query_string = urllib.parse.urlencode({'limit': limit, 'offset': offset}) path_pattern = f'/payment-holds/?{query_string}' ows_client_mock.post('ows-abacus-account', path_pattern, json=account_ids).mock( return_value=httpx.Response(status_code=400, json='error') ) with pytest.raises( OwsAccountException, match=f'ERROR in POST {path_pattern.replace("?", r"\?")}' ): bulk_get_payment_holds(account_ids, limit, offset)